概述
近日碰到一个有趣的bug。具体情况是:通过HTML.fromHtml的方式给TextView设置富文本内容。
通过TagHandler.handleTag方法,处理自定义标签。在文本中插入一个自定义ReplacementSpan。
然而,当我的自定义span的宽度变化时,存在一个临界值,会使得该自定义ReplacementSpan有时绘制不出来。(正常应该如第二个图所示)
原因
我在tagHandler中使用了空格占位,替换自定义span
output.append(" ");
output.setSpan(mySpan, output.length() - 1, output.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
在debug跟踪TextView绘制过程源码后,发现TextView在计算一行放多少文字时,会判断,在哪个字符处换行。
//Layout.java
private int getLineVisibleEnd(int line, int start, int end) {
CharSequence text = mText;
char ch;
if (line == getLineCount() - 1) {
return end;
}
for (; end > start; end--) {
ch = text.charAt(end - 1);
if (ch == '\n') {
return end - 1;
}
if (!TextLine.isLineEndSpace(ch)) {
break;
}
}
return end;
}
//TextLine.java
public static boolean isLineEndSpace(char ch) {
return ch == ' ' || ch == '\t' || ch == 0x1680
|| (0x2000 <= ch && ch <= 0x200A && ch != 0x2007)
|| ch == 0x205F || ch == 0x3000;
}
在isLineEndSpace方法中,有几种字符刚好处于一行最末尾的时候会被忽略!
解决方案
在tagHandler中使用其他字符占位,只要不是isLineEndSpace中的几种字符就可以。
output.append(";");
output.setSpan(mySpan, output.length() - 1, output.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);