在最近的项目中,有个列表需要展示类似微信朋友圈的全文功能,点击全文展示所有的内容,点击隐藏全文,展示原本的文本。
设置TextView最多只能展示5行,超过5行的时候展示省略号(TextView设置最大行数的同时支持Span属性的一些坑,已经在LinkMovementMethod那些坑中描述)。我们只要知道当前展示的文字长度超过了5行,就可以知道是否要展示全文按钮,可以使用addOnGlobalLayoutListener()在TextView绘制完成后进行展示文字长度的判断,我选择自定义TextView,在onMeasure()中进行判断。
一开始在网上搜罗了一些方法后,感觉还挺简单的,码上代码:
1 | public class SpannableTextView extends TextView { |
在使用了这个TextView的RecyclerView的adapter里面
1 | linkText.setCallback(new SpannableTextView.TextViewShowCallback() { |
跑了一下,看到全文和收起可以正常使用了,美滋滋的以为so easy啊。然鹅,过不了多久就收到qa的bug邮件,说她的文本都没有全文按钮。不能啊,我这明明好好的呢,一定是见鬼了(我的代码不存在bug的,不接受反驳╭(๑¯д¯๑)╮)。多拿了几个机型跑了一下,发现Android 8.0以上的机器都不能正常显示全文按钮,跟debug后发现是lineEnd的值不准,返回的是全文的长度。翻google无果后,就想还是得靠自己,开始翻源码,然后!!!就发现了一个大坑。。
在sdk 27的源码中,getLineEnd()源码如下:
1 | /** |
看到getLineStart上面写着,如果参数line和目前TextView的line一致的话,就返回文本的全部长度,我整个人陷入了沉思。。。这么存在的一个方法有什么用啊,什么用。。。为什么Android 5.0可以用啊,可以用。。。都这样了,那只能自己想办法计算了,最后计算方法如下:
1 | public class SpannableTextView extends TextView { |
在Android 5.0 7.0 8.0都跑了一下,这下真的可以正常展示。。。
写代码一分钟,解bug一天。。。╮(﹀_﹀)╭
最后附上在RecyclerView中的item里,点击全文和收起的实现代码:
1 | // 标志展开的item的位置 |