android html 字体颜色代码,Android TextView通过解析html显示不同颜色和大小
先贴一张效果图
效果
介绍
通过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显示不同颜色和大小相关推荐
- android 图片变颜色代码,Android -对图片Drawable进行变色
Android 图片DrawableCompat利用setTint()对图片Drawable进行变色 1.利用color资源对Drawable变色 Drawable对象的来源不限制,可以是从资源get ...
- android 获取手机颜色代码,Android获取当前主题的颜色属性
安卓代码中获取当前主题颜色方法的两种方法: 第一种方法: TypedArray array = getTheme().obtainStyledAttributes(new int[]{ android ...
- android提取图片颜色代码,Android 中动态提取图片中颜色作为主题色
功能需求 一个页面中顶部显示一张图片(图片从网络加载),此时需要根据图片的颜色来动态调整顶部标题栏的背景色. 技术要求 Android 调色板支持库 实现过程 1.添加调色板支持库 dependenc ...
- 修改React Native Android'默认字体颜色为黑色
修改React Native Android'默认字体颜色为黑色 找到res/values/styles.xml文件插入代码 <style name="AppTheme" p ...
- android 沉浸式状态栏字体颜色,改变Android状态栏字体颜色和实现沉浸式状态栏
目前已知的改变Android状态栏字体颜色的方法只有3种情况下可以实现,分别是手机是MIUI系统.魅族手机以及Android6.0.改变颜色方法分别如下: * 改变小米的状态栏字体颜色为黑色, 要求M ...
- php文字红色代码,IOS_IOS中一段文字设置多种字体颜色代码,给定range和需要设置的颜色, - phpStudy...
IOS中一段文字设置多种字体颜色代码 给定range和需要设置的颜色,就可以给一段文字设置多种不同的字体颜色,使用方法如下: [self fuwenbenLabel:contentLabel Font ...
- html字体颜色 html中设置字体颜色代码 字体颜色获取
html字体颜色 html中设置字体颜色代码 字体颜色获取 html字体颜色设置更改,html设置字体颜色代码方法有哪些 DIVCSS5为大家介绍在html中设置字体颜色方法,字体颜色修改方法,字体颜 ...
- 诛仙服务器显示横线,诛仙手游字变颜色怎么弄_诛仙手游字体颜色代码大全_快吧手游...
诛仙手游字变颜色怎么弄?相信好多小伙伴在聊天的过程中遇到这种情况,别人的字体会有各种字体出现,在这里,小编整理了诛仙手游字体颜色代码大全!快来学习一下吧! 字体颜色代码大全 [[950000]aaff ...
- CSS中文说明及字体颜色代码
/* 网站链接总的CSS定义:可定义内容为链接字体颜色.样式等 */ a{text-decoration: none;} /* 链接无下划线,有为underline */ a:link {color: ...
最新文章
- 配置VMware ESXi 5事件发送到SYSLOG服务器
- .9-Vue源码之AST(5)
- pipfile和pipfile.lock、virtualenv、pipenv、pip
- android 如何使用SAX解析XML
- 从 0 到 1 实现浏览器端沙盒运行环境
- linux重启后地址不是之前设置的静态地址的解决方案
- Java讲课笔记26:File类
- 【学习总结】Git学习-参考廖雪峰老师教程十-自定义Git
- request.setAttribute()与getParameter() 的区别
- 3.14 在金山做的动态建模讲座
- 利用Python进行数据分析--数据聚合与分组运算1
- android AsyncTask 详细例子
- matlab练习程序(生成加密p文件)
- gentoo Wireless Configuration
- 诺顿5月17日病毒库误报,导致系统文件被删除
- linux vim修改字符串,Linux的vim查找和替换字符串
- umijs 隐藏开发工具_Umi UI 插件开发 - UmiJS 中文文档
- 小球碰撞python代码_python开发的小球完全弹性碰撞游戏代码_python_脚本之家
- 我被美团会员割了韭菜
- springboot+美容院会员管理系统 毕业设计-附源码191740
热门文章
- 2021年茶艺师(中级)考试题及茶艺师(中级)考试报名
- 黑客入侵你的电脑,你怕吗?
- php xml expat,PHP 和 XML: 使用expat函数(一)
- 调用文曲星里的英语词典中的语音(游戏发音处理)
- 什么是互联网舆情监测分析系统,TOOM舆情监测云服务有哪些内容?
- 推荐:成为大数据开发全能高手的100篇文章
- win10家庭版,夜间模式打开无反应
- CodeForces-691E Xor-sequences(矩阵快速幂)
- jenkins+gitlab实现自动化部署平台
- 文档预览:在浏览器中预览查看 Office 文档