背景
开发中很常见的需求:需要让 TextView
控件多行展示,并在超出限制行数后,在最后一行的末尾显示省略号;如果未超过限制行数,则正常显示即可。
实现代码
private int mShowLine = -1;// 变量,存储指定显示的行数
boolean showEllipsis = false;// 是否超出限制并添加省略号。true表示超出限制添加省略号
/**
* 【超出指定行数,在最后一行结尾添加省略号】
* 【未超出支持行数,正常显示】
* 如果设置了 maxLines 属性,跟 showLines 参数相比较,取较小值进行行数展示
* @param tv 文本控件对象
* @param showLines 指定展示行数
* @param originText 原始文本
*/
private void ellipsizeEnd(TextView tv, int showLines, String originText){
if (tv == null || TextUtils.isEmpty(originText)){
return;
}
mShowLine = showLines;
tv.setText(originText);
tv.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
try {
int lineCount = tv.getLineCount();
System.out.println(":> ### lineCount = " + lineCount);
// 如果设置了 maxLine 属性的情况
if (tv.getMaxLines() > 0 && tv.getMaxLines() < mShowLine){
mShowLine = tv.getMaxLines();
}
// lineCount(实际展示行数) 、mShowLine(指定行数)
if (lineCount <= mShowLine){
mShowLine = lineCount;
showEllipsis = false;
}else {
showEllipsis = true;
}
// 需要在结尾添加省略号的情况
if (showEllipsis){
Layout layout = tv.getLayout();
int sum = 0;// 需要展示多少个字
for (int i = 0;i < mShowLine;i++){
sum += (layout.getLineEnd(i) - layout.getLineStart(i));
}
System.out.println(":> ### sum = " + sum);
String showStr = originText.substring(0, sum-3) + "...";
tv.setText(showStr);
}
// 及时的清除 OnGlobalLayoutListener 监听
if (Build.VERSION.SDK_INT >= 16) {
tv.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
tv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}catch (Exception e){
e.printStackTrace();
}
}
});
}
思路如下:
- 获取
ViewTreeObserver
对象,给其添加OnGlobalLayoutListener
监听(当一个视图树的布局发生改变时,可以被ViewTreeObserver
监听到)。 - 在上面的监听方法中进行相关判断逻辑的编写。
- 设置原始文本,获取到实际展示的行数 lineCount,然后跟指定需要展示的行数
mShowLine
进行比较,当lineCount
更小时,说明超出限制了,需要在结尾添加省略号。 - 假如
mShowLine
是 2 且是需要添加省略号的情况,那就获取前mShowLine
行每行的字数总和sum
,然后截取原始字符的前sum-3
个文本,最后再拼接上省略号...
文本即可。
示例演示
未超出指定行数
textview
控件xml
声明如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.MainActivity">
<TextView
android:id="@+id/tv_info"
android:textSize="24sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="" />
</LinearLayout>
- 调用如下:
String originText = "举目观天下,唯我最为珍。蓝天白云翠,山河任遨游。家园是田园,共筑梦想基。人民众志成城,祖国真可爱。山间溪水涟漪荡,树叶微动沙沙响。翠岭云霞相映照,远峰苍翠入云藏。";
ellipsizeEnd(tv_info, 3, originText);
- 效果图示:
超出指定行数
- 调用如下:
String originText = "举目观天下,唯我最为珍。蓝天白云翠,山河任遨游。家园是田园,共筑梦想基。人民众志成城,祖国真可爱。山间溪水涟漪荡,树叶微动沙沙响。翠岭云霞相映照,远峰苍翠入云藏。";
ellipsizeEnd(tv_info, 2, originText);
- 效果图示:
总结
上面的方法可以放到一个工具类里,然后方便统一调用。然后基于上面的逻辑可以扩展出更多省略号位置展示的情况,同学们可以自己去尝试一下。
下期有缘再见!