前言
我们都知道,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);
}
该方法满足只显示一行时需要省略指定位置的情况,多行的话可以加上行数进行进一步处理。