浅谈 Android 15 新 API:确保 TextView 完整展示、不被切断~

前言

很多语言和文字拥有特殊的、复杂的写法、画法,一个字符可能延伸到前一个字符的区域,甚至后一个字符的区域。

如果文字的宽度没有做针对这种文字做额外的加宽处理,那么文字整体在边界区域会出现被切掉的现象。

比如如下的文字类型,最右边的文字 ร์ 的右上角的符号没有显示完全。

转存失败,建议直接上传图片文件

针对这个痛点,Android 15 进行了优化,如果 app 面向 Android 15 及更高的版本后,可以采用 setUseBoundsForWidth() 设置为 true,就可以拓宽 TextView 的显示区域。

转存失败,建议直接上传图片文件

可以看到,采用新设置之后,最右边的文字(ร์)的右上角的符号能完全显示了。

说明

宽度的调整会给已有的布局引起垂直方向上不对齐的可能性问题,所以该设置默认是关闭的。

另外,事实上光依赖 setUseBoundsForWidth() 还不够,还需要将 shiftDrawingOffsetForStartOverhang 设置为 true,那这个 API 干啥用的,我们在后面的实战环节会进行介绍。

除了 set 方法,Android 15 也提供了 getUseBoundsForWidth()getShiftDrawingOffsetForStartOverhang() 供开发者动态地调用。

当然,这两项设置在 XML 中也有相应的 attribute 支持,供开发者在布局中直接使用。

  • android:useBoundsForWidth bool
  • android:shiftDrawingOffsetForStartOverhang bool

实战

我们以 cursive 字体下的 Java 文字为例,进行该 API 的尝试。

xml
 代码解读
复制代码
    <TextView
        android:fontFamily="cursive"
        android:text="java" /> 

转存失败,建议直接上传图片文件

默认情况下没有效果,字符 J 的左下角被切掉了。

正如文档所说 Android 15 上 useBoundsForWidth 未指定的情况下,width 不会拓宽。

xml
 代码解读
复制代码
<TextView
     android:fontFamily="cursive"
     android:text="java"
     android:useBoundsForWidth="true" /> 

转存失败,建议直接上传图片文件

仍然没有效果,因为还要依赖 shiftDrawingOffsetForStartOverhang 属性。

xml
 代码解读
复制代码
<TextView
     android:fontFamily="cursive"
     android:text="java"
     android:useBoundsForWidth="true"
     android:shiftDrawingOffsetForStartOverhang="true"/> 

转存失败,建议直接上传图片文件

可以看到有效果了,J 字符的左边展示完全了。

Inspecting 检查

让我们 dump 角度 double confirm 下 View 的尺寸上是否有变化。

最简单快速的是使用 LayoutInspector。

转存失败,建议直接上传图片文件

转存失败,建议直接上传图片文件

通过 inspecting,咱们发现视觉上明明拓宽了的 TextView 在 inspector 里展示的 width 却都是 60dp。

Dumpsys 确认

暂时不确定这是 Inpector 的 bug 还是确实如此,我们尝试用 adb dump 下宽高。

bash
 代码解读
复制代码
    adb shell dumpsys activity top

我们用 adb dump 一下试试。

bash
 代码解读
复制代码
      ACTIVITY com.ellison.osvdemo/.textView.TextViewWidthActivity d53efc9 pid=6004 userId=0 uid=10196 displayId=0(type=INTERNAL)
        ...
        View Hierarchy:
          com.android.internal.policy.DecorView{2c56827 V.E...... R....... 0,0-1080,2400 aid=0}[]
            android.widget.LinearLayout{8f36ad4 V.E...... ........ 0,0-1080,2400}
              android.view.ViewStub{e29447d G.E...... ......I. 0,0-0,0 #10201cb android:id/action_mode_bar_stub}
              android.widget.FrameLayout{1e6f72 V.E...... ........ 0,63-1080,2337}
                androidx.appcompat.widget.ActionBarOverlayLayout{7165fc3 V.E...... ........ 0,0-1080,2274 #7f080092 app:id/decor_content_parent}
                  androidx.appcompat.widget.ContentFrameLayout{9866040 V.E...... ........ 0,147-1080,2274 #1020002 android:id/content}
                      ...
                      com.google.android.material.textview.MaterialTextView{df946ed V.ED..... ........ 461,394-619,539 #7f0801fa app:id/textview4}
                      com.google.android.material.textview.MaterialTextView{fbebfb3 V.ED..... ........ 449,933-631,1078 #7f0801fb app:id/textview5}
                      com.google.android.material.textview.MaterialTextView{db064e9 V.ED..... ........ 449,1472-631,1617 #7f0801fc app:id/textview6}

可以看到几个 TextView 在左上右下的坐标:

  • 默认情况下的 Java 文字 TextView 的坐标: 461, 394 ~ 619, 539,宽度是 619 - 461 = 158px
  • 仅开启 setUseBoundsForWidth 情况下的 Java 文字 TextView 的坐标: 449, 933 ~ 631, 1078,宽度是 631 - 449 = 182px
  • 外加开启 shiftDrawingOffsetForStartOverhang 情况下的 Java 文字 TextView 的坐标: 449, 1472 ~ 631, 1617,宽度也是 631 - 449 = 182px

至此,大家应该能得到结论:

  • setUseBoundsForWidth 实际已经拓宽了宽度,但没有减少文字在 TextView 内部的 padding,导致仍被切掉、显示不全
  • shiftDrawingOffsetForStartOverhang 并没有控制宽度,则是在 draw 的时候向右 offset,促使文字不被切掉

我们将效果截图放大,大家仔细看下:

转存失败,建议直接上传图片文件

细致对比之后,可以看出,两者宽度实际上一致,唯一不同的是后者将内容往右进行了平移。

结语

几乎每年的 Android 系统升级,Google 都会针对 TextView 基础组件进行改动或新的支持。

今年的 Android 15 版本也是一样,针对 TextView 进行了 3 处修改:

  1. 避免文本切断的 setUseBoundsForWidth API 和 shiftDrawingOffsetForStartOverhang API
  2. 依据 locale 选择适合的 TextView 行高数值的 setLocalePreferredLineHeightForMinimumUsed API
  3. 设置的字体测量最小值的 setMinimumFontMetrics API
  4. 针对 TextView 内容换行的专用属性 <nobreak> API

本文阐述了第 1 点,后续将逐步阐述其他几个变化,敬请期待。

作者:TechMerger
链接:https://juejin.cn/post/7370170468780933135
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值