由于在android 中的Html源码中对html标签的支持不是很完全,在使用textview加载html自定义字体样式的时候遇到坑了,就是font标签不支持size属性,查看源码中发现没有去解析size属性
// Html源码部分private static void startFont(SpannableStringBuilder text,Attributes attributes) {// 解析颜色 String color = attributes.getValue("", "color");// 解析faceString face = attributes.getValue("", "face");int len = text.length();text.setSpan(new Font(color, face), len, len, Spannable.SPAN_MARK_MARK);}
所以如下这样写size是没有效果的,只显示颜色
String text = "<font color='red' size='50px'>" + "要显示的数据" + "</font>";Spanned spanned = Html.fromHtml(text);
==>>>>>>>>>>>>>>>>>>>>>分割线>>>>>>>>>>>>>>>>>>>>>==
由于android对html标签解析最终也是通过各种span进行拼接形成对应的样式:
以下是android中提供的各种span及用途
BackgroundColorSpan 背景色 ClickableSpan 文本可点击,有点击事件 ForegroundColorSpan 文本颜色(前景色) MaskFilterSpan修饰效果,如模糊(BlurMaskFilter)、浮雕(EmbossMaskFilter) MetricAffectingSpan 父类,一般不用 RasterizerSpan 光栅效果 StrikethroughSpan 删除线(中划线) SuggestionSpan 相当于占位符 UnderlineSpan 下划线 AbsoluteSizeSpan 绝对大小(文本字体) DynamicDrawableSpan 设置图片,基于文本基线或底部对齐。 ImageSpan 图片 RelativeSizeSpan 相对大小(文本字体) ReplacementSpan 父类,一般不用 ScaleXSpan 基于x轴缩放 StyleSpan 字体样式:粗体、斜体等 SubscriptSpan 下标(数学公式会用到) SuperscriptSpan 上标(数学公式会用到) TextAppearanceSpan 文本外貌(包括字体、大小、样式和颜色) TypefaceSpan 文本字体 URLSpan 文本超链接
接下来我们就通过Html.TagHandler来自定义标签实现设置字体大小的功能
此处我定义标签名为:myfont
此处的调用方式如下:
String text = "<myfont color='red' size='50px'>" + "要显示的数据" + "</myfont>";Spanned spanned = Html.fromHtml(text, null, new HtmlTagHandler("myfont"));
关键代码在HtmlTagHandler里面处理自定义标签myfont:
public class HtmlTagHandler implements Html.TagHandler {// 自定义标签名称private String tagName;// 标签开始索引private int startIndex = 0;// 标签结束索引private int endIndex = 0;// 存放标签所有属性键值对final HashMap<String, String> attributes = new HashMap<>();public HtmlTagHandler(String tagName) {this.tagName = tagName;}@Overridepublic void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {// 判断是否是当前需要的tagif (tag.equalsIgnoreCase(tagName)) {// 解析所有属性值parseAttributes(xmlReader);if (opening) {startHandleTag(tag, output, xmlReader);}else {endEndHandleTag(tag, output, xmlReader);}}}public void startHandleTag(String tag, Editable output, XMLReader xmlReader) {startIndex = output.length();}public void endEndHandleTag(String tag, Editable output, XMLReader xmlReader) {endIndex = output.length();// 获取对应的属性值String color = attributes.get("color");String size = attributes.get("size");size = size.split("px")[0];// 设置颜色if (!TextUtils.isEmpty(color)) {output.setSpan(new ForegroundColorSpan(Color.parseColor(color)), startIndex, endIndex,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);}// 设置字体大小if (!TextUtils.isEmpty(size)) {output.setSpan(new AbsoluteSizeSpan(Integer.parseInt(size)), startIndex, endIndex,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);}}/*** 解析所有属性值** @param xmlReader*/private void parseAttributes(final XMLReader xmlReader) {try {Field elementField = xmlReader.getClass().getDeclaredField("theNewElement");elementField.setAccessible(true);Object element = elementField.get(xmlReader);Field attsField = element.getClass().getDeclaredField("theAtts");attsField.setAccessible(true);Object atts = attsField.get(element);Field dataField = atts.getClass().getDeclaredField("data");dataField.setAccessible(true);String[] data = (String[]) dataField.get(atts);Field lengthField = atts.getClass().getDeclaredField("length");lengthField.setAccessible(true);int len = (Integer) lengthField.get(atts);for (int i = 0; i < len; i++) {attributes.put(data[i * 5 + 1], data[i * 5 + 4]);}} catch (Exception e) {}}}
如果以下方式没有效果:
String text = "<myfont color='red' size='50px'>" + "要显示的数据" + "</myfont>";Spanned spanned = Html.fromHtml(text, null, new HtmlTagHandler("myfont"));
可在myfont标签前面添加一个随意标签实现如:
String text = "<p><myfont color='red' size='50px'>" + "要显示的数据" + "</myfont></p>";Spanned spanned = Html.fromHtml(text, null, new HtmlTagHandler("myfont"));
如果不想自定义tag显示字体大小和颜色可参考