自动缩放文字的TextView

需求:根据文字长度自动缩小文字大小

最近做项目遇到一个场景,在做类似淘宝选择商品数量的页面,点“+”数字增,点“-”数字减,想到一个问题,布局样式固定,暂时不做可输入数量,只能通过加减号变更数量,文本宽度固定,如果真的有人一直点加号,文字宽度大于了实际控件的宽度,能不能让文字自动缩小

虽然Android有AppCompatTextView已经有这种效果,但是仅限于8.0及以上系统,难道做的软件只能允许Android8.0系统以上的手机能用??这显然不行!!!

于是,自定义吧,虽然网上搜一下,也有类似的博文,但是发现是不是有点复杂,于是,整理一下思路:

  1. 文字不超过TextView宽度不用进行缩放
  2. 为了两边留有一定间隔,当文本宽度大于TextView宽度-左右间隔时,开始缩放
  3. 缩放比例如何计算??其实很简单,文本宽度/(TextView宽度-左右间隔)即可
  4. 比例计算好,设置字体大小即可

文本宽度的计算,在网上有篇文章“关于 Android 测量文字宽度的方法”,我是通过百度快照进去看的,因为现在博客园改成必须注册用户才可看,有点恶心。
文中讲到两点:

1、测量绝对文本的长度
2、测量相对文本的长度
什么是绝对文本呢?
就是指那些字号、字体、粗细等属性不受在所运行的硬件设备上的 Android 系统的配置所影响文本。例如:自定义View时通过Canvas绘制出来的文本;
而相对文本在使用上就广泛很多了。例如直接用 TextView 展示的文本、网页上的文本、手机短信内容文本等。相对文本在字号、字体、粗细程度上除了受应用开发时的配置影响以外还会间接地受到系统设置的影响。例如在 Android 的系统设置 – 显示 – 字体大小 中的配置就会间接地影响到相对文本的显示效果。

绝对长度:通过paint.measureText(txt);获得

相对长度:通过Layout.getDesiredWidth(text.toString(), 0, text.length(), textPaint);获得

我这里采用相对长度。
上代码

import android.content.Context
import android.graphics.Canvas
import android.text.Layout
import android.text.TextPaint
import android.util.AttributeSet
import android.util.TypedValue
import androidx.appcompat.widget.AppCompatTextView

class AutoScaleTextView : AppCompatTextView{

    private var textPaint: TextPaint = paint
    private var txtSize: Float

    constructor(context: Context?) : this(context,null)
    constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs,0)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ){
        txtSize = textPaint.textSize
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        canvas?.let {
            if(text.isNotEmpty()){
                //绝对文本大小,字号、字体、粗细等属性不受在所运行的硬件设备上的 Android 系统的配置所影响文本
                //float length = getPaint().measureText(content.toString());

                //相对大小,受上述属性影响
                val txtLen = Layout.getDesiredWidth(text.toString(),0,text.length,textPaint)
                if(txtLen>width-10){//当字体长度大于宽度-10的时候,按比例缩放
                    val scale = width/txtLen
                    setTextSize(TypedValue.COMPLEX_UNIT_PX,txtSize*scale)
                }else{
                    setTextSize(TypedValue.COMPLEX_UNIT_PX,txtSize)
                }
            }
        }
    }
}

效果如下
初始:
自动缩放文字的TextView
长文本:
自动缩放文字的TextView
这就结束了,没有添加任何新的属性,TextView平时怎么使用还怎么使用!
贴一段布局中的示例,修改text就可以及时看到效果
初始状态


<包名.widget.AutoScaleTextView
                        android:id="@+id/tv_num"
                        android:layout_width="44dp"
                        android:layout_height="match_parent"
                        android:gravity="center"
                        android:maxLines="1"
                        android:text="1"
                        android:textColor="@color/main_color"
                        android:textSize="20dp"
                        android:textStyle="bold"/>

长文本状态:

<包名.widget.AutoScaleTextView
                        android:id="@+id/tv_num"
                        android:layout_width="44dp"
                        android:layout_height="match_parent"
                        android:gravity="center"
                        android:maxLines="1"
                        android:text="123456789"
                        android:textColor="@color/main_color"
                        android:textSize="20dp"
                        android:textStyle="bold"/>
上一篇:Android 在代码中修改TextView的DrawableRight等方向上的图片


下一篇:Android屏幕适配技巧