Android TextView 在指定位置自动省略字符

4,897 阅读2分钟

前言

我们都知道,Android中可以通过 android:ellipsize="xxx"来指定文字过长时的省略方式,但是这种方式只能局限在文字后省略、文字前省略以及文字中央省略。

需求

有时候因为产品经理的需求,我们需要在指定的位置省略过长的文字。举个例子,对于文件名来说,产品经理希望用户能知道当前文件名的后缀,但是在文件过长时又想省略文件名过长的部分,就会出现AAA...mp4这样的显示形式,这种显示形式是无法通过设置android:ellipsize来实现的。

对于 "这可能是一个专门刁难程序员的很长的文件名.mp4"

  • 错误示范

  • 正确示范

解决方案

解决此问题的原理是通过textView.getPaint().measureText(String text)方法来获取文字在TextView上所占宽度。

  • 获取原文字在控件上占满的长度
String originText = "这可能是一个专门刁难程序员的很长的文件名.mp4";
//获取原文字长度
float originTextWidth = textView.getPaint().measureText(originText);
//获取控件长度
float textViewWidth = textView.getWidth();
  • 判断控件是否可以装满文字
//控件长度大于文字长度 直接显示
 if (textViewWidth >= originTextWidth) {
    textView.setText(originText);
}else {
    //获取指定省略位置
}
  • 获取指定省略位置
 //获取指定省略位置 对于文件名来说最后的"."是省略部分的标志 
 int lastIndexOfPoint = originText.lastIndexOf(".");
 if (lastIndexOfPoint == -1) {
    //找不到 直接显示
     textView.setText(originText);
 } else {
    //找到了 对字符串切分
 }
  • 根据省略位置对字符串切分
//前缀 文件名 "这可能是一个专门刁难程序员的很长的文件名"
String prefixText = originText.substring(0, lastIndexOfPoint);
//后缀 添加省略符号 "...mp4"
String suffixText = ".." + originText.substring(lastIndexOfPoint, originText.length());

*不断递减指定位置前的字符串,以此来获取满足条件的前缀字符串。

float prefixWidth = textView.getPaint().measureText(prefixText);
float suffixWidth = textView.getPaint().measureText(suffixText);

//后缀太长 不处理
if (suffixWidth > textViewWidth){
    textView.setText(originText);
}else {
    //每减少前缀一个字符都去判断是否能塞满控件
    while (textViewWidth - prefixWidth < suffixWidth) {
        prefixText = prefixText.substring(0, prefixText.length() - 1);
        //关键
        prefixWidth = textView.getPaint().measureText(prefixText);
    }
    //能塞满
    textView.setText(prefixText + suffixText);
}

该方法满足只显示一行时需要省略指定位置的情况,多行的话可以加上行数进行进一步处理。