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

本文为稀土掘金技术社区首发签约文章,30天内禁止转载,30天后未获授权禁止转载,侵权必究!

前言

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

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

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

针对这个痛点,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 点,后续将逐步阐述其他几个变化,敬请期待。

DEMO

AndroidOSVDemo

参考

相关推荐
2501_944525541 天前
Flutter for OpenHarmony 个人理财管理App实战 - 预算详情页面
android·开发语言·前端·javascript·flutter·ecmascript
清蒸鳜鱼1 天前
【Mobile Agent——Droidrun】MacOS+Android配置、使用指南
android·macos·mobileagent
2501_915918411 天前
HTTPS 代理失效,启用双向认证(mTLS)的 iOS 应用网络怎么抓包调试
android·网络·ios·小程序·https·uni-app·iphone
峥嵘life1 天前
Android EDLA CTS、GTS等各项测试命令汇总
android·学习·elasticsearch
Cobboo1 天前
i单词上架鸿蒙应用市场之路:一次从 Android 到 HarmonyOS 的完整实战
android·华为·harmonyos
天下·第二1 天前
达梦数据库适配
android·数据库·adb
定偶1 天前
MySQL知识点
android·数据结构·数据库·mysql
iwanghang1 天前
Android Studio 2023.2.1 新建项目 不能选择Java 解决方法
android·ide·android studio
似霰1 天前
JNI 编程指南10——从内存角度看引用类型
android·jni
南墙上的石头1 天前
Android端 人工智能模型平台开发实战:模型服务部署与运维平台
android·运维