有这样一个需求,界面上需要显示一个标题文本,但是该标题的文案长度是不固定的,要求标题的文案全部显示出来,不能用省略号显示,并且标题所占的宽高是固定的。例如标题的文案为 “这是标题,该标题的名字比较长,产品要求不换行全部显示出来”,如下图所示,第一个为不符合需求的标题,第二个为符合需求的标题。

android 字体 粗细 绘制 android字体大小适配_android


也就是说 TextView 控件的宽高需要固定,然后根据标题的文案长度动态改变文字大小,也就是上图第二个标题的效果。那是怎么实现的呢?

以前的做法一般是测量 TextView 字体所占的宽度与 TextView 控件的宽度对比,动态改变 TextView 的字体大小,写起来即麻烦又耗性能。但是现在不用这么麻烦了,Android 8.0 新增了用来动态改变 TextView 字体大小的新特性 Autosizing TextViews,只需要简单设置一下属性即可。

例如上图中符合需求的效果可以这样写:
xml 方式

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">

    <TextView
        android:layout_width="340dp"
        android:layout_height="50dp"
        android:background="@drawable/shape_bg_008577"
        android:gravity="center_vertical"
        android:maxLines="1"
        android:text="这是标题,该标题的名字比较长,产品要求不换行全部显示出来"
        android:textSize="18sp"
        android:autoSizeTextType="uniform"
        android:autoSizeMaxTextSize="18sp"
        android:autoSizeMinTextSize="10sp"
        android:autoSizeStepGranularity="1sp"/>
</LinearLayout>

可以看到 TextView 控件多了如下属性:

  1. autoSizeTextType:设置 TextView 是否支持自动改变文本大小,none 表示不支持,uniform 表示支持。
  2. autoSizeMinTextSize:最小文字大小,例如设置为10sp,表示文字最多只能缩小到10sp。
  3. autoSizeMaxTextSize:最大文字大小,例如设置为18sp,表示文字最多只能放大到18sp。
  4. autoSizeStepGranularity:缩放粒度,即每次文字大小变化的数值,例如设置为1sp,表示每次缩小或放大的值为1sp。

上面的只是针对于8.0的设备有效,如果想要兼容8.0以下设备,则需要用AppCompatTextView 代替 TextView,并且上面几个属性的命名空间需要用 app 命名空间。如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:gravity="center">

    <android.support.v7.widget.AppCompatTextView
        android:layout_width="340dp"
        android:layout_height="50dp"
        android:background="@drawable/shape_bg_008577"
        android:gravity="center_vertical"
        android:maxLines="1"
        android:text="这是标题,该标题的名字比较长,产品要求不换行全部显示出来"
        android:textSize="18sp"
        app:autoSizeTextType="uniform"
        app:autoSizeMaxTextSize="18sp"
        app:autoSizeMinTextSize="10sp"
        app:autoSizeStepGranularity="1sp"/>
</LinearLayout>

如果当前的 xml 文件对应的 Activity 继承的是 AppCompatActivity可以实现向下兼容,如果继承的是 Activity 或 FragmentActivity 是不能达到兼容的。
动态编码方式
使用 TextViewCompat 的setAutoSizeTextTypeWithDefaults()方法设置 TextView 是否支持自动改变文字大小,setAutoSizeTextTypeUniformWithConfiguration() 方法设置最小文字大小、最大文字大小与缩放粒度。如下所示:

TextView tvText = findViewById(R.id.tv_text);
TextViewCompat.setAutoSizeTextTypeWithDefaults(tvText,TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM);
TextViewCompat.setAutoSizeTextTypeUniformWithConfiguration(tvText,10,18,1, TypedValue.COMPLEX_UNIT_SP);
  • setAutoSizeTextTypeWithDefaults() 参数1为需要动态改变文字大小的
    TextView,参数2为是否支持自动改变文字大小的类型,AUTO_SIZE_TEXT_TYPE_UNIFORM表示支持,AUTO_SIZE_TEXT_TYPE_NONE
    表示不支持。
  • setAutoSizeTextTypeUniformWithConfiguration() 参数1为需要动态改变文字大小的
    TextView,参数2、3、4分别为最小文字大小、最大文字大小与缩放粒度,参数5为参数2、3、4的单位,例如sp 、dp、px等。
    同样,如果要兼容8.0以下设备,要么在 xml 中用 AppCompatTextView 代替TextView,要么当前 Activity 继承 AppCompatActivity。
    小结
    Autosizing TextViews是Android 8.0 新增的特性,可以用来动态改变 TextView 字体大小。如果要兼容8.0以下设备,则需要满足以下2个条件中的其中一个。
  • 在 xml 中用 AppCompatTextView 代替 TextView,并且上面几个属性的命名空间用app 命名空间。
  • 当前 Activity 继承 AppCompatActivity,而不是 Activity 或 FragmentActivity。