获取TextView行数
最近在做评论这块的功能,产品提了一个这样的需求,当用户评论的内容大于5行的时候添加一个可以折叠的小按钮,点击按钮可以显示全部内容,再次点击按钮又把评论内容全部显示出来。刚看到这个需求的时候感觉还蛮简单,于是一阵噼里啪啦之后,噢,发现不行,感觉蛮有意思的,哈哈,于是就有了以下的文章。来-----走起。
第一步:分析
1.既然是评论内容,我们索性就拿TextView来显示就好了。要做到折叠的效果,首先我们要判断当前的内容是否超过五行,如果超过就吧五行以后的内容不显示,如果不超过就直接显示全部内容。当内容超过五行而且点击展开全部内容按钮就显示全部内容,展开后按钮会变成收起内容,点击收起内容又会只显示五行内容。
2.既然是判断行数,大家一定会想到TextView有一个 getLineCount() 方法,通过这个方法就可以获取到行数,没错,就是通过它来获取TextView行数。但是有一个问题,当我们给TextView设置了内容之后马上调用getLineCount()方法的时候,你会惊奇的发现它返回来的书籍竟然是0,惊不惊喜,意不意外。顿时是不是感觉应该不对啊,调用了这个方法后应该是可以获取到行数的啊。不急,我来给你讲一下。
3.很多人觉得给TextView设置了内容之后就可以直接获取它的行数了,其实不然。当我们给TextView设置了内容到TextView完全展示出来是有一个复杂的绘制过程的,它需要计算计算TextView的位置,计算TextView可以展示多大的宽高,最后才会展示在手机上面的。说白了就是在给TextView设置了内容之后,它还没来得及绘制你就去调用TextView的getLineCount()方法的话是不会获取到它的行数的,正确的做法就是等待TextView 绘制完成再做处理。我们可以通过以下方法监听:getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {}); 这个方法的前部分getViewTreeObserver() 是获取TextView的视图叔,然后给它设置一个绘制前的监听方法addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {}); 这个监听是在视图绘制前回调的,又有好事的同学就问了,上面不是说要等待它绘制完成后才能够获取行数吗(其实那个是就是我,哈哈),其实是大家对视图的绘制流程还不是很理解,当视图经历过onMeasure()和onLyout()之后就可以获取到它的宽高,也就可以获取它的行数了。还不明白视图绘制的同学自行去了解该方面的知识了,这里就不做扩展了。到这里我们先上几张需求效果图。
第二步:实施
到这里我就直接上代码了
tv_content.setMaxLines(50); //因为一开始我们不知道内容又多少,所以要设置足够的行数 tv_content.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { //这个监听的回调是异步的,在监听完以后一定要把绘制监听移除,不然这个会一直回调,导致界面错乱 tv_content.getViewTreeObserver().removeOnPreDrawListener(this); int line = tv_content.getLineCount(); if(line>4){ item.setMoreLine(true); item.setFullLineShow(false); tv_content.setMaxLines(4); tv_more_tab.setVisibility(View.VISIBLE); }else{ tv_more_tab.setVisibility(View.INVISIBLE); item.setMoreLine(false); item.setFullLineShow(true); } return true; } });