先贴一张效果图

效果

介绍

通过SpannableString、SpannableStringBuilder可以很方便的给TextView加上各种各样的样式,比如不同的颜色和大小,这里就不多说了,具体可以参考下面这篇文章:

SpannableString与SpannableStringBuilder使用

TextView通过使用Html.fromHtml方法可以加载html片段,但是它支持的标签并不是很多:

private void handleStartTag(String tag, Attributes attributes) {

if (tag.equalsIgnoreCase("br")) {

// We don't need to handle this. TagSoup will ensure that there's a for each

// so we can safely emite the linebreaks when we handle the close tag.

} else if (tag.equalsIgnoreCase("p")) {

handleP(mSpannableStringBuilder);

} else if (tag.equalsIgnoreCase("div")) {

handleP(mSpannableStringBuilder);

} else if (tag.equalsIgnoreCase("strong")) {

start(mSpannableStringBuilder, new Bold());

} else if (tag.equalsIgnoreCase("b")) {

start(mSpannableStringBuilder, new Bold());

} else if (tag.equalsIgnoreCase("em")) {

start(mSpannableStringBuilder, new Italic());

} else if (tag.equalsIgnoreCase("cite")) {

start(mSpannableStringBuilder, new Italic());

} else if (tag.equalsIgnoreCase("dfn")) {

start(mSpannableStringBuilder, new Italic());

} else if (tag.equalsIgnoreCase("i")) {

start(mSpannableStringBuilder, new Italic());

} else if (tag.equalsIgnoreCase("big")) {

start(mSpannableStringBuilder, new Big());

} else if (tag.equalsIgnoreCase("small")) {

start(mSpannableStringBuilder, new Small());

} else if (tag.equalsIgnoreCase("font")) {

startFont(mSpannableStringBuilder, attributes);

} else if (tag.equalsIgnoreCase("blockquote")) {

handleP(mSpannableStringBuilder);

start(mSpannableStringBuilder, new Blockquote());

} else if (tag.equalsIgnoreCase("tt")) {

start(mSpannableStringBuilder, new Monospace());

} else if (tag.equalsIgnoreCase("a")) {

startA(mSpannableStringBuilder, attributes);

} else if (tag.equalsIgnoreCase("u")) {

start(mSpannableStringBuilder, new Underline());

} else if (tag.equalsIgnoreCase("sup")) {

start(mSpannableStringBuilder, new Super());

} else if (tag.equalsIgnoreCase("sub")) {

start(mSpannableStringBuilder, new Sub());

} else if (tag.length() == 2 &&

Character.toLowerCase(tag.charAt(0)) == 'h' &&

tag.charAt(1) >= '1' && tag.charAt(1) <= '6') {

handleP(mSpannableStringBuilder);

start(mSpannableStringBuilder, new Header(tag.charAt(1) - '1'));

} else if (tag.equalsIgnoreCase("img")) {

startImg(mSpannableStringBuilder, attributes, mImageGetter);

} else if (mTagHandler != null) {

mTagHandler.handleTag(true, tag, mSpannableStringBuilder, mReader);

}

}

查看源码应该只支持这几种,不过看最后一句代码发现它是支持自定义标签处理的,就是说你可以自己重写TagHandler去实现。

思路

结合前面说的SpannableString和参考Html类源码可以实现我们这篇文章的需求,如果你只是想解析html在TextView上显示不同的颜色,那系统已经实现了,但前提是要用font标签,比如这样:

测试TextView显示不同颜色和大小

在Html类源码中发现:

private static void startFont(SpannableStringBuilder text,

Attributes attributes) {

String color = attributes.getValue("", "color");

String face = attributes.getValue("", "face");

int len = text.length();

text.setSpan(new Font(color, face), len, len, Spannable.SPAN_MARK_MARK);

}

private static void endFont(SpannableStringBuilder text) {

int len = text.length();

Object obj = getLast(text, Font.class);

int where = text.getSpanStart(obj);

text.removeSpan(obj);

if (where != len) {

Font f = (Font) obj;

if (!TextUtils.isEmpty(f.mColor)) {

if (f.mColor.startsWith("@")) {

Resources res = Resources.getSystem();

String name = f.mColor.substring(1);

int colorRes = res.getIdentifier(name, "color", "android");

if (colorRes != 0) {

ColorStateList colors = res.getColorStateList(colorRes, null);

text.setSpan(new TextAppearanceSpan(null, 0, 0, colors, null),

where, len,

Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

}

} else {

int c = Color.getHtmlColor(f.mColor);

if (c != -1) {

text.setSpan(new ForegroundColorSpan(c | 0xFF000000),

where, len,

Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

}

}

}

if (f.mFace != null) {

text.setSpan(new TypefaceSpan(f.mFace), where, len,

Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

}

}

}

系统处理了font标签的color和face属性,但是没有处理size属性,这个让人很郁闷,没办法,我们只有通过自定义TagHandler来处理了,这里我参考了这篇文章:

Android 多样化显示TextView以及扩展Html自定义标签

至此,TextView解析html显示不同颜色和大小的功能通过自定义TagHandler已经可以实现了,但是这种方式也有一定的局限性,就是后台给你返回的html片段的样式要使用标签中的属性,就像我上面举例的font中的color属性,但是可能后台返回的数据不一定是这样,我们后台返回的就是这样的:

选项C

如果是这样的情况,那就需要再对style属性进行解析,获取里面的样式属性,所以这里只是给大家提供一个思路,具体怎么处理还是要看后台返回的数据。

结尾

最后附上我处理style属性的自定义TagHandler,有不对的地方,欢迎大家指正!

package wdcloud.testdemo;

import android.content.Context;

import android.content.res.ColorStateList;

import android.content.res.Resources;

import android.graphics.Color;

import android.text.Editable;

import android.text.Html;

import android.text.Spannable;

import android.text.Spanned;

import android.text.TextUtils;

import android.text.style.AbsoluteSizeSpan;

import android.text.style.ForegroundColorSpan;

import android.text.style.TextAppearanceSpan;

import android.util.Log;

import org.xml.sax.XMLReader;

import java.lang.reflect.Field;

import java.util.HashMap;

import java.util.Map;

public class CustomTagHandler implements Html.TagHandler {

private final String TAG = "CustomTagHandler";

private int startIndex = 0;

private int stopIndex = 0;

private ColorStateList mOriginColors;

private Context mContext;

public CustomTagHandler(Context context,ColorStateList originColors){

mContext = context;

mOriginColors = originColors;

}

@Override

public void handleTag(boolean opening, String tag, Editable output,

XMLReader xmlReader) {

processAttributes(xmlReader);

if(tag.equalsIgnoreCase("span")){

if(opening){

startSpan(tag, output, xmlReader);

}else{

endSpan(tag, output, xmlReader);

attributes.clear();

}

}

}

public void startSpan(String tag, Editable output, XMLReader xmlReader) {

startIndex = output.length();

}

public void endSpan(String tag, Editable output, XMLReader xmlReader){

stopIndex = output.length();

String color = attributes.get("color");

String size = attributes.get("size");

String style = attributes.get("style");

if (!TextUtils.isEmpty(style)){

analysisStyle(startIndex,stopIndex,output,style);

}

if (!TextUtils.isEmpty(size)) {

size = size.split("px")[0];

}

if(!TextUtils.isEmpty(color)){

if (color.startsWith("@")) {

Resources res = Resources.getSystem();

String name = color.substring(1);

int colorRes = res.getIdentifier(name, "color", "android");

if (colorRes != 0) {

output.setSpan(new ForegroundColorSpan(colorRes), startIndex, stopIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

}

} else {

try {

output.setSpan(new ForegroundColorSpan(Color.parseColor(color)), startIndex, stopIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

} catch (Exception e) {

e.printStackTrace();

reductionFontColor(startIndex,stopIndex,output);

}

}

}

if (!TextUtils.isEmpty(size)) {

int fontSizePx = 16;

if (null != mContext){

fontSizePx = DisplayUtil.sp2px(mContext,Integer.parseInt(size));

}

output.setSpan(new AbsoluteSizeSpan(fontSizePx), startIndex, stopIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

}

}

final HashMap attributes = new HashMap();

private void processAttributes(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);

/**

* MSH: Look for supported attributes and add to hash map.

* This is as tight as things can get :)

* The data index is "just" where the keys and values are stored.

*/

for(int i = 0; i < len; i++)

attributes.put(data[i * 5 + 1], data[i * 5 + 4]);

}

catch (Exception e) {

}

}

/**

* 还原为原来的颜色

* @param startIndex

* @param stopIndex

* @param editable

*/

private void reductionFontColor(int startIndex,int stopIndex,Editable editable){

if (null != mOriginColors){

editable.setSpan(new TextAppearanceSpan(null, 0, 0, mOriginColors, null),

startIndex, stopIndex,

Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

}else {

editable.setSpan(new ForegroundColorSpan(0xff2b2b2b), startIndex, stopIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

}

}

/**

* 解析style属性

* @param startIndex

* @param stopIndex

* @param editable

* @param style

*/

private void analysisStyle(int startIndex,int stopIndex,Editable editable,String style){

Log.e(TAG,"style:"+style);

String[] attrArray = style.split(";");

Map attrMap = new HashMap<>();

if (null != attrArray){

for (String attr:attrArray){

String[] keyValueArray = attr.split(":");

if (null != keyValueArray && keyValueArray.length == 2){

// 记住要去除前后空格

attrMap.put(keyValueArray[0].trim(),keyValueArray[1].trim());

}

}

}

Log.e(TAG,"attrMap:"+attrMap.toString());

String color = attrMap.get("color");

String fontSize = attrMap.get("font-size");

if (!TextUtils.isEmpty(fontSize)) {

fontSize = fontSize.split("px")[0];

}

if(!TextUtils.isEmpty(color)){

if (color.startsWith("@")) {

Resources res = Resources.getSystem();

String name = color.substring(1);

int colorRes = res.getIdentifier(name, "color", "android");

if (colorRes != 0) {

editable.setSpan(new ForegroundColorSpan(colorRes), startIndex, stopIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

}

} else {

try {

editable.setSpan(new ForegroundColorSpan(Color.parseColor(color)), startIndex, stopIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

} catch (Exception e) {

e.printStackTrace();

reductionFontColor(startIndex,stopIndex,editable);

}

}

}

if (!TextUtils.isEmpty(fontSize)) {

int fontSizePx = 16;

if (null != mContext){

fontSizePx = DisplayUtil.sp2px(mContext,Integer.parseInt(fontSize));

}

editable.setSpan(new AbsoluteSizeSpan(fontSizePx), startIndex, stopIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

}

}

}

使用方式:

TextView tv_ExtendTest = (TextView) findViewById(R.id.tv_extend_test);

tv_ExtendTest.setText(Html.fromHtml(htmlContent,null,new CustomTagHandler(TextViewExtendActivity.this,tv_ExtendTest.getTextColors())));

测试发现高版本Android系统中(如8.0),系统已经把span给解析了,所以不会再把span的解析回调给自定义TagHandler,这种情况下只需换一个系统没有解析的标签,最好是自定义的,比如之类的。

android html 字体颜色代码,Android TextView通过解析html显示不同颜色和大小相关推荐

  1. android 图片变颜色代码,Android -对图片Drawable进行变色

    Android 图片DrawableCompat利用setTint()对图片Drawable进行变色 1.利用color资源对Drawable变色 Drawable对象的来源不限制,可以是从资源get ...

  2. android 获取手机颜色代码,Android获取当前主题的颜色属性

    安卓代码中获取当前主题颜色方法的两种方法: 第一种方法: TypedArray array = getTheme().obtainStyledAttributes(new int[]{ android ...

  3. android提取图片颜色代码,Android 中动态提取图片中颜色作为主题色

    功能需求 一个页面中顶部显示一张图片(图片从网络加载),此时需要根据图片的颜色来动态调整顶部标题栏的背景色. 技术要求 Android 调色板支持库 实现过程 1.添加调色板支持库 dependenc ...

  4. 修改React Native Android'默认字体颜色为黑色

    修改React Native Android'默认字体颜色为黑色 找到res/values/styles.xml文件插入代码 <style name="AppTheme" p ...

  5. android 沉浸式状态栏字体颜色,改变Android状态栏字体颜色和实现沉浸式状态栏

    目前已知的改变Android状态栏字体颜色的方法只有3种情况下可以实现,分别是手机是MIUI系统.魅族手机以及Android6.0.改变颜色方法分别如下: * 改变小米的状态栏字体颜色为黑色, 要求M ...

  6. php文字红色代码,IOS_IOS中一段文字设置多种字体颜色代码,给定range和需要设置的颜色, - phpStudy...

    IOS中一段文字设置多种字体颜色代码 给定range和需要设置的颜色,就可以给一段文字设置多种不同的字体颜色,使用方法如下: [self fuwenbenLabel:contentLabel Font ...

  7. html字体颜色 html中设置字体颜色代码 字体颜色获取

    html字体颜色 html中设置字体颜色代码 字体颜色获取 html字体颜色设置更改,html设置字体颜色代码方法有哪些 DIVCSS5为大家介绍在html中设置字体颜色方法,字体颜色修改方法,字体颜 ...

  8. 诛仙服务器显示横线,诛仙手游字变颜色怎么弄_诛仙手游字体颜色代码大全_快吧手游...

    诛仙手游字变颜色怎么弄?相信好多小伙伴在聊天的过程中遇到这种情况,别人的字体会有各种字体出现,在这里,小编整理了诛仙手游字体颜色代码大全!快来学习一下吧! 字体颜色代码大全 [[950000]aaff ...

  9. CSS中文说明及字体颜色代码

    /* 网站链接总的CSS定义:可定义内容为链接字体颜色.样式等 */ a{text-decoration: none;} /* 链接无下划线,有为underline */ a:link {color: ...

最新文章

  1. 配置VMware ESXi 5事件发送到SYSLOG服务器
  2. .9-Vue源码之AST(5)
  3. pipfile和pipfile.lock、virtualenv、pipenv、pip
  4. android 如何使用SAX解析XML
  5. 从 0 到 1 实现浏览器端沙盒运行环境
  6. linux重启后地址不是之前设置的静态地址的解决方案
  7. Java讲课笔记26:File类
  8. 【学习总结】Git学习-参考廖雪峰老师教程十-自定义Git
  9. request.setAttribute()与getParameter() 的区别
  10. 3.14 在金山做的动态建模讲座
  11. 利用Python进行数据分析--数据聚合与分组运算1
  12. android AsyncTask 详细例子
  13. matlab练习程序(生成加密p文件)
  14. gentoo Wireless Configuration
  15. 诺顿5月17日病毒库误报,导致系统文件被删除
  16. linux vim修改字符串,Linux的vim查找和替换字符串
  17. umijs 隐藏开发工具_Umi UI 插件开发 - UmiJS 中文文档
  18. 小球碰撞python代码_python开发的小球完全弹性碰撞游戏代码_python_脚本之家
  19. 我被美团会员割了韭菜
  20. springboot+美容院会员管理系统 毕业设计-附源码191740

热门文章

  1. 2021年茶艺师(中级)考试题及茶艺师(中级)考试报名
  2. 黑客入侵你的电脑,你怕吗?
  3. php xml expat,PHP 和 XML: 使用expat函数(一)
  4. 调用文曲星里的英语词典中的语音(游戏发音处理)
  5. 什么是互联网舆情监测分析系统,TOOM舆情监测云服务有哪些内容?
  6. 推荐:成为大数据开发全能高手的100篇文章
  7. win10家庭版,夜间模式打开无反应
  8. CodeForces-691E Xor-sequences(矩阵快速幂)
  9. jenkins+gitlab实现自动化部署平台
  10. 文档预览:在浏览器中预览查看 Office 文档