背景
#在我们的项目中,展示文字是很常见的需求,但是在线上展示中发现,有些信息是特殊字符展示的,而且这些字符的高度会导致TextView的高度变高(与正常字符比)。
效果如下:
很明显,带特殊字符的高度,会非常高!
解决方案
结论
该问题是因为Google在API28 之后对TextView做了优化,增加了mUseFallbackLineSpacing
属性,该属性会在出现高度过高的字符时,自动扩充高度,来讲对应的字符展示完整。
方案
textView.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
isFallbackLineSpacing = false
}
}
解决后展示效果
问题探查过程
1、确定问题原因
因为只有包含特殊字符的地方高度不一样,所以怀疑是该特殊字符的高度变化导致。在TextView通过获取TextView的Layout的,遍历获取每一行的高度,发现果然是包含了特殊字符的高度比不包含的高。
针对这个问题想到的解决方案是:自己绘制,自己制作Layout,根据位置将被拔高的文字绘制回中央。
2、在onDraw中使用StaticLayout自行绘制。
StaticLayout创建后,遍历每一行,并将内容绘制出来,问题出现了,我自己创建的StaticLayout遍历绘制后,并没有出现字体被拔高的情况。于是推测,会不会是系统创建的Layout有哪些属性是加入了该功能?
3、查阅源代码
找到TextView中创建StaticLayout的地方,将其构造中的内容copy出来,自己设置,结果发现,当我将 isUseFallbackLineSpacing 参数设置为true时,我绘制的结果和系统绘制出来的一样,是被拔高了的。于是将其设置为fasle,发现高度被压缩回正常字体大小了。
4、 确定方案
有了上面的认知,就继续查看TextView有没有提供设置对应属性的方法,结果发现了 setFallbackLineSpacing方法,在API 28 也就是 P 及以上,将其设置为false 即可。在官方的注释中,如果你的App支持 缅甸语或者藏语,需要将它必须设置为true。这里可以根据字符判断内容有没有缅甸语或者藏语,去设置吧。目前我们的App不支持该两种语言,直接设置为false,没什么太大影响。