- HtmlSpanner基于https://github.com/NightWhistler/HtmlSpanner, 主体代码基本全部copy,扩展了两点:
- 原始版本在解析Html时使用了HTMLCleaner解析库,但是在我引入的过程中发现该库以及其依赖的库引入了太多的方法,有点得不偿失。因此Html解析这部分被我进行了替换。对解析功能进行了抽象接口: 在net.nightwhistler.htmlspanner.parse中,基于SDK内置的javax.xml.parsers和org.w3c.dom进行了解析的实现替换以及XML元素的表示,使得方法数控制在一个相对较小的量级。
- 根据项目需求引入了一部分新的html标签支持,以及新的html标签属性支持。
- 引入HtmlSpanner的目的是为了提升格式化文本的效率,其对比SDK内置的Html类的有这些优势:
- 可以支持Html标签的属性,Html类虽然也可以,但是支持的很有限,并且不能自定义属性。同时Html对标签的支持还有版本兼容问题。
- 支持新的Html标签很方便,Html虽然也可以,但是不能成体系化。
- 最重要的一点是,这部分代码是完全归属于项目的,debug以及扩展都非常自由,不必受限于Android本身的框架和实现。
- HtmlSpanner使用栈来在解析过程中缓存Html文本格式解析信息,在最终解析完以后基于栈先进后出对文本进行格式化(applySpan, 使用栈是为了迎合Html标签嵌套的规则),详细过程参考HtmlSpanner的fromHtml函数流程即可。
- HtmlSpanner支持的标签可以参考HtmlSpanner的registerBuiltInHandlers()方法,其列出了所有当前支持的标签类型。
- 要增加对一个新标签的支持,也可以参考HtmlSpanner的registerBuiltInHandlers()中的实现: 自定义一个TagNodeHandler, 然后使用registerHandler将表签名和自定义的Handler关联起来。
- 有一个需要注意的事项: Android特有的销毁-恢复机制在恢复一个SpannableString时,只能支持特定类型的Span: 可以参见TextUtils中的CHAR_SEQUENCE_CREATOR和writeToParcel()方法,这就意味着某些不被支持的Span在经过销毁-恢复之后就丢失了,导致HtmlSpanner解析出来的SpannableString被破坏了。想要规避这个问题,一个比较hack的方法是禁止控件的SavedState功能(比如TextView,这样其就不会自己进行内容恢复),如果TextView的内容在每次销毁-恢复之后会被代码进行设置(即不会导致动态信息的丢失),禁止SavedState是可行的。
- HtmlSpanner是支持css的,不过没有需求,没有进行过运用。