浅谈 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

参考

相关推荐
董可伦1 小时前
Dinky 安装部署并配置提交 Flink Yarn 任务
android·adb·flink
每次的天空2 小时前
Android学习总结之Glide自定义三级缓存(面试篇)
android·学习·glide
zimoyin2 小时前
Kotlin 协程实战:实现异步值加载委托,对值进行异步懒初始化
java·前端·kotlin
恋猫de小郭2 小时前
如何查看项目是否支持最新 Android 16K Page Size 一文汇总
android·开发语言·javascript·kotlin
flying robot4 小时前
小结:Android系统架构
android·系统架构
xiaogai_gai4 小时前
有效的聚水潭数据集成到MySQL案例
android·数据库·mysql
鹅鹅鹅呢5 小时前
mysql 登录报错:ERROR 1045(28000):Access denied for user ‘root‘@‘localhost‘ (using password Yes)
android·数据库·mysql
在人间负债^5 小时前
假装自己是个小白 ---- 重新认识MySQL
android·数据库·mysql
Unity官方开发者社区5 小时前
Android App View——团结引擎车机版实现安卓应用原生嵌入 3D 开发场景
android·3d·团结引擎1.5·团结引擎车机版
进击的CJR8 小时前
MySQL 8.0 OCP 英文题库解析(三)
android·mysql·开闭原则