1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.intentresolver.widget 18 19 import android.content.Context 20 import android.graphics.drawable.Drawable 21 import android.util.AttributeSet 22 import android.view.Gravity 23 import android.widget.TextView 24 25 /** 26 * A TextView that supports a badge at the end of the text. If the text, when centered in the view, 27 * leaves enough room for the badge, the badge is just displayed at the end of the view. Otherwise, 28 * the necessary amount of space for the badge is reserved and the text gets centered in the 29 * remaining free space. 30 */ 31 class BadgeTextView : TextView { 32 constructor(context: Context) : this(context, null) 33 34 constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) 35 36 constructor( 37 context: Context, 38 attrs: AttributeSet?, 39 defStyleAttr: Int 40 ) : this(context, attrs, defStyleAttr, 0) 41 42 constructor( 43 context: Context?, 44 attrs: AttributeSet?, 45 defStyleAttr: Int, 46 defStyleRes: Int 47 ) : super(context, attrs, defStyleAttr, defStyleRes) { 48 super.setGravity(Gravity.CENTER) 49 defaultPaddingLeft = paddingLeft 50 defaultPaddingRight = paddingRight 51 } 52 53 private var defaultPaddingLeft = 0 54 private var defaultPaddingRight = 0 55 setPaddingnull56 override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) { 57 super.setPadding(left, top, right, bottom) 58 defaultPaddingLeft = paddingLeft 59 defaultPaddingRight = paddingRight 60 } 61 setPaddingRelativenull62 override fun setPaddingRelative(start: Int, top: Int, end: Int, bottom: Int) { 63 super.setPaddingRelative(start, top, end, bottom) 64 defaultPaddingLeft = paddingLeft 65 defaultPaddingRight = paddingRight 66 } 67 68 /** Sets end-sided badge. */ 69 var badgeDrawable: Drawable? = null 70 set(value) { 71 if (field !== value) { 72 field = value 73 super.setBackground(value) 74 } 75 } 76 onMeasurenull77 override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { 78 super.setPadding(defaultPaddingLeft, paddingTop, defaultPaddingRight, paddingBottom) 79 super.onMeasure(widthMeasureSpec, heightMeasureSpec) 80 val badge = badgeDrawable ?: return 81 if (badge.intrinsicWidth <= paddingEnd) return 82 var maxLineWidth = 0f 83 for (i in 0 until layout.lineCount) { 84 maxLineWidth = maxOf(maxLineWidth, layout.getLineWidth(i)) 85 } 86 val sideSpace = (measuredWidth - maxLineWidth) / 2 87 if (sideSpace < badge.intrinsicWidth) { 88 super.setPaddingRelative( 89 paddingStart, 90 paddingTop, 91 paddingEnd + badge.intrinsicWidth - sideSpace.toInt(), 92 paddingBottom 93 ) 94 super.onMeasure(widthMeasureSpec, heightMeasureSpec) 95 } 96 } 97 setBackgroundnull98 override fun setBackground(background: Drawable?) { 99 badgeDrawable = null 100 super.setBackground(background) 101 } 102 setGravitynull103 override fun setGravity(gravity: Int): Unit = error("Not supported") 104 } 105