android Html.fromHtml font 标签支持设置字体大小和颜色

由于在android 中的Html源码中对html标签的支持不是很完全,在使用textview加载html自定义字体样式的时候遇到坑了,就是font标签不支持size属性,查看源码中发现没有去解析size属性

// Html源码部分
 private static void startFont(SpannableStringBuilder text,
                                  Attributes attributes) {
         // 解析颜色                        
        String color = attributes.getValue("", "color");
        // 解析face
        String face = attributes.getValue("", "face");

        int len = text.length();
        text.setSpan(new Font(color, face), len, len, Spannable.SPAN_MARK_MARK);
    }

所以如下这样写size是没有效果的,只显示颜色

String text = "" + "要显示的数据" + "";
Spanned spanned = Html.fromHtml(text);

==>>>>>>>>>>>>>>>>>>>>>分割线>>>>>>>>>>>>>>>>>>>>>==

由于android对html标签解析最终也是通过各种span进行拼接形成对应的样式:

以下是android中提供的各种span及用途

  1. BackgroundColorSpan 背景色
  2. ClickableSpan 文本可点击,有点击事件
  3. ForegroundColorSpan 文本颜色(前景色)
  4. MaskFilterSpan修饰效果,如模糊(BlurMaskFilter)、浮雕(EmbossMaskFilter)
  5. MetricAffectingSpan 父类,一般不用
  6. RasterizerSpan 光栅效果
  7. StrikethroughSpan 删除线(中划线)
  8. SuggestionSpan 相当于占位符
  9. UnderlineSpan 下划线
  10. AbsoluteSizeSpan 绝对大小(文本字体)
  11. DynamicDrawableSpan 设置图片,基于文本基线或底部对齐。
  12. ImageSpan 图片
  13. RelativeSizeSpan 相对大小(文本字体)
  14. ReplacementSpan 父类,一般不用
  15. ScaleXSpan 基于x轴缩放
  16. StyleSpan 字体样式:粗体、斜体等
  17. SubscriptSpan 下标(数学公式会用到)
  18. SuperscriptSpan 上标(数学公式会用到)
  19. TextAppearanceSpan 文本外貌(包括字体、大小、样式和颜色)
  20. TypefaceSpan 文本字体
  21. URLSpan 文本超链接

接下来我们就通过Html.TagHandler来自定义标签实现设置字体大小的功能
此处我定义标签名为:myfont

此处的调用方式如下:

String text = "" + "要显示的数据" + "";
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 attributes = new HashMap<>();

        public HtmlTagHandler(String tagName) {
            this.tagName = tagName;
        }

        @Override
        public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {
            // 判断是否是当前需要的tag
            if (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 = "" + "要显示的数据" + "";
Spanned spanned = Html.fromHtml(text, null, new HtmlTagHandler("myfont"));

可在myfont标签前面添加一个随意标签实现如:

String text = "

" + "要显示的数据" + "

"
; Spanned spanned = Html.fromHtml(text, null, new HtmlTagHandler("myfont"));

如果不想自定义tag显示字体大小和颜色可参考

你可能感兴趣的:(android,android进阶)