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元素,此函数可能不会生效,原因未知。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明AI阅读 16,105评论 3 119
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 11,942评论 0 17
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 14,716评论 1 92
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 14,578评论 2 59
  • 玉玺专指皇帝的玉印,始于秦朝,古代印、玺通称,主要材质为金或玉。玺始出于周,到了周朝才有玺和印之分,皇帝用的印叫玺...
    潇湘妃子JC阅读 4,878评论 0 0

友情链接更多精彩内容