安卓TextView的lineHeight*lineCount!=height问题,解决不支持滚动的系统下对多页Text进行分页

前言

最近在做运行在墨水屏系统上的程序,由于墨水屏刷新率比较低,所以系统内的软件是不允许滚动和加动画的(在逻辑上)

这样就导致了平时在普通安卓手机上很简单的程序,在墨水屏系统上就很麻烦,比如多页的应用,普通安卓机直接搞一个ScrollView和RecyclerView就可以了,但墨水屏系统上你需要自己计算每页展示多少内容,然后在进行分页

旧方式分页

由于墨水屏的特性,我们要实现一个跨页的TextView,就需要进行分页处理

ps:为什么不适用自己绘制?因为要兼容富文本

最开始使用的系统是基于安卓8的,其版本中TextView的行高lineHeight*行数lineCount=TextView的高度,所以最开始的TextView分页算法也很简单:

先用页面高度/tv行高获得一页能展示多少行,然后通过tv总行数/单页行数计算得到一共多少页,最后在最底部画一个矩形盖住底部最后一行可能展示不全的text就可以了,伪代码如下:

ps:如果在低版本系统上发现lineHeight*lineCount始终和TextView的height查了固定数值的话,那可能是TextView的默认边距没有去掉,去掉的代码如下:

includeFontPadding = false

新方式分页

后来用了新的安卓11系统后,发现lineHeight*lineCount!=height了,而且后续也上了很多种富文本,所以上面的方式就不太合适了,于是就需要找一种新的分页方式了

通过扒拉TextView的源码发现,TextView计算Text和布局是通过Layout对象来实现的,于是我们就扒拉Layout的源码

通过看源码发现包含普通Text和普通富文本的TextView中的Layout对象是StaticLayout,然后发现StaticLayout将其中计算的行位置等的数据保存在了内部变量mLines中,然后通过看源码结合别的博客发现TextView的行位置计算方式有两种:

分为5线和7线两种(我的推测,如果有问题请大佬们指出)

其中5线的示意图如下(图片来自承香墨影大佬的博客,侵删): 

七线的没找到图...

 而不管是哪种行位置的计算方式,其实我们并不用管太多,因为Layout方法已经给出了方法让我们获取相应行的相应位置了:

StaticLayout的getLineTop实现:

 

虽然没有直接提供行最底部的y轴的值,但是提供了行最顶部的y轴获取的方法getLineTop(line),所以我们只需要拿到下一行的lineTop并减1像素,那就是本行的底部的y轴了,这样我们就可以计算TextView每行的高度并分页了,伪代码如下:

 最后再灵活绘制以下底部矩形盖住显示不全的文字就可以了

结语

安卓代码量太大了,每个部分可能都很复杂,如果想搞清楚一个东西,那就直接去看其本质(源码)

end

猜你喜欢

转载自blog.csdn.net/qq_33505109/article/details/125426843