Android中使用HTML.fromHtml为文字设置颜色和大小

前言

由于项目需求需要实现一个TextView中含有不同大小不同颜色的文本,但TextView本身根本无法实现,出于写法的精简性我又不想另外多写几个TextView,所以打算采用HTML类中的fromHtml函数通过html标签解析实现。

正文

由于Android对html标签支持不是太好,在将font标签中的size进行赋值后发现大小的设置并没有生效,随后我查看了源码,发现源码中并没有解析size属性,源码如下:

    private void startFont(Editable text, Attributes attributes) {
        String color = attributes.getValue("", "color");
        String face = attributes.getValue("", "face");

        if (!TextUtils.isEmpty(color)) {
            int c = getHtmlColor(color);
            if (c != -1) {
                start(text, new Foreground(c | 0xFF000000));
            }
        }

        if (!TextUtils.isEmpty(face)) {
            start(text, new Font(face));
        }
    }

由图中的源码得知,按照常规的html写法,以下这段代码中的size属性是不生效的。

String text = "<font color='red' size='50px'>" + "要显示的数据" + "</font>";
            Spanned spanned = Html.fromHtml(text);

所以,我们需要使用TagHandler进行自定义标签来实现设置字体大小的功能。

首先自定义一个MyHtmlTagHandler,继承自HTML.TagHandler:

public class MyHtmlTagHandler implements Html.TagHandler {

    private String tagName;

    private int startIndex = 0;

    private int endIndex = 0;

    final HashMap<String, String> attributes = new HashMap<>();

    public MyHtmlTagHandler(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(size)) {
            output.setSpan(new AbsoluteSizeSpan(Integer.parseInt(size)), startIndex, endIndex,
                    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }

        // 设置颜色
        if (!TextUtils.isEmpty(color)) {
            output.setSpan(new ForegroundColorSpan(Color.parseColor(color)), 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) {

        }
    }
}

接下来的使用(我这里采取了两个字符串入参的文字风格设置):

    public static android.text.Spanned colorString(String str1,String str1FontColor,String str1FontSize,String str2,String str2FontColor,String str2FontSize) {

        try {
            String text = "<br/><myfont color='" + str1FontColor + "' size='" + str1FontSize + "'>" + str1 + "</myfont>"
                    + "<myfont color='" + str2FontColor + "' size='" + str2FontSize + "'>" + str2 + "</myfont>";
            Spanned spanned = Html.fromHtml(text, null, new MyHtmlTagHandler("myfont"));

            return spanned;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

接着将生成的Spanned对象放入TextView的setText函数即可。
PS:如果不在HTML标签最前面加入其他HTML元素,此函数可能不会生效,原因未知。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值