首先,让我们看一看下面可能是在 TextView 中显示 HTML 的四种方式,您可以先判断下他们是否会正确的显示 HTML。
1. TextView#setText()
strings.xml:
<string name="what_the_html"><b>What</b> <i>the</i> <u>Html</u></string>
Activity.java:
textView.setText(R.string.what_the_html);
2. Resources#getString()
textView.setText(getString(R.string.what_the_html));
3. Html.fromHtml()
textView.setText(
Html.fromHtml(
getString(R.string.what_the_html)
)
);
4. Html.fromHtml() + CDATA
strings.xml:
<string name="what_the_html">
<![CDATA[
<b>What</b> <i>the</i> <u>Html</u>
?]]>
</string>
Activity.java:
textView.setText(
Html.fromHtml(
getString(R.string.what_the_html)
)
);
如果您没有判断对是 1 和 4 能正确显示 HTML,那么或许您需要继续阅读下面的内容。
Problem: String vs CharSequence
首先,我们要理解 TextView#setText() 方法接受的是一个 CharSequence 参数,而 Resources#getString() 返回的是一个 String。当然,String 和 CharSequence 这两个并不总是可以互换的。
而我们平时还是能往 setText() 中传递 String 的原因是 String 实现了 CharSequence。
还有一个同样实现了 CharSequence 的就是 Spanned,其支持使用被称为 "span" 的东西来修改文本的显示效果。Spans 是一组很小的对象,包含了有关如何绘制一段文本的信息,Android 系统中大量的用到了它。
一些常见的包括:
- StyleSpan, 粗体和斜体
- UnderlineSpan, 下划线
- TypefaceSpan, 自定义字体
- ImageSpan, 插入图像 (比如 emojis)
- URLSpan, 超链接
ps: 1. EditText 中闪烁的光标也是通过 span 实现的。 2. TextView 和 EditText 中的文本选中效果也是通过 span 实现的。
正确做法
当 HTML 需要被解析时,Android 同样会使用 span 来讲 HTML 标签转换为 TextView 可以理解并在屏幕上绘制的格式。为了做到这点,Android 提供了两个选项:
1. Resources#getText()
Resources#getText() 能解析到字符串中包含的 HTML 标记,并返回一个携带了样式的 CharSequence 对象。当 HTML 可以从 string 资源文件中直接得到时,这应该是我们首选的方式:
CharSequence styledText = getText(R.string.what_the_html);
textView.setText(styledText);
而 Resources#getString() 为什么错误,我们也可以通过看源代码来理解:
Resources.java:
public String getString(@StringRes int resId) {
return getText(resId).toString();
}
可以看到其内部还是调用的 getText(),但 toString() 会抛弃掉所有的样式,String 是没有携带样式信息的。
2. Html.fromHtml()
Resources#getText() 内部其实还是使用了 Html.fromHtml() 来解析 HTML 标签的,也可以直接用于动态生成 HTML 的情况。Html.fromHtml() 的返回值同样也是一个 Spanned 对象。
Html.java:
public static Spanned fromHtml(String source) {
...
}
总结:当需要从资源文件中获取 html 并展示时,使用 Resource#getText() 而不是 Resource#getString()。当需要动态显示 HTML 时,使用 Html.fromHtml()。
感谢原文作者,原文链接:https://zhuanlan.zhihu.com/p/27830863