项目中需要使用富文本来显示消息通知,由于消息的类型多达几十种,且这些不同类型消息显示的文案由服务端控制,这里文案需要使用富文本来显示不同颜色、大小、字体的文字,所幸是textView支持富文本显示。具体实现方法有两种:
一、使用HTML 标记设置样式
将待显示字符串添加到strings文件中。例如:
<?xml version="1.0" encoding="utf-8"?><resources> <string name="welcome">Welcome to<b>Android</b>!</string></resources>
支持的 HTML 标签包括:
<a href="...">创建超文本链接
<b>黑体字
<big>字体加大
<blockquote>从两边缩进文本
<br>换行插入换行符
<cite>引用,通常是斜体
<dfn>述语定义
<div align="...">用来排版大块HTML段落,也用于格式化表
<em>强调文本(通常是斜体加黑体)
<font size="..." color="..."face="...">设置字体大小从1到7,颜色使用名字或RGB的十六进制值
<h1>至<h6>标题
<i>斜体字
<img src="...">图片
<p>创建一个段落
<small>字体缩小
<strike>加删除线
<strong>加重文本(通常是斜体加黑体)
<sub>下标字
<sup>上标字
<tt>打字机风格的字体
<u>下划线
如果将带样式文本资源作为格式字符串。 正常情况下是行不通的,因为 String.format(String,Object...) 方法会去除字符串中的所有样式信息。要解决这个问题只能编写带转义实体的 HTML 标签,在完成格式设置后,这些实体可通过fromHtml(String) 恢复。 例如:
1.将您带样式的文本资源存储为HTML 转义字符串:
<resources> <string name="welcome_messages">Hello, %1$s! You have <b>%2$d newmessages</b>.</string></resources>
在这个带格式的字符串中,添加了 <b> 元素。请注意,开括号使用 < 表示法进行了 HTML 转义。
2.然后照常设置字符串格式,但还要调用 fromHtml(String) 以将HTML 文本转换成带样式文本:
Resources res = getResources();String text =String.format(res.getString(R.string.welcome_messages), username, mailCount);CharSequence styledText = Html.fromHtml(text);
由于 fromHtml(String) 方法将设置所有 HTML 实体的格式,因此务必要使用 htmlEncode(String) 对您用于带格式文本的字符串中任何可能的 HTML 字符进行转义。 例如,如果您向 String.format() 传递的字符串参数可能包含“<”或“&”之类的字符,则必须在设置格式前进行转义,这样在通过 fromHtml(String) 传递带格式字符串时,字符就能以原始形式显示出来。 例如:
String escapedUsername = TextUtil.htmlEncode(username);Resources res =getResources();String text =String.format(res.getString(R.string.welcome_messages), escapedUsername, mailCount);CharSequence styledText = Html.fromHtml(text);
二、使用Spannable 设置样式
Spannable 可以对颜色和字体粗细等属性进行样式设置。 首先使用 SpannableStringBuilder 构造文本内容,然后为文本设置 android.text.style 包中定义的样式,常见的样式有StrikethroughSpan、StyleSpan、ForegroundColorSpan等。例如,为某段文字内容加上带颜色和删除线的粗体样式。
public CharSequence renderSpan(Stringtext, String color, boolean isBold, boolean isDelete) {
if(TextUtils.isEmpty(color)) {
color ="#272934";//默认值
}
if(TextUtils.isEmpty(text)) {
return null;
}
SpannableStringBuilder span = new SpannableStringBuilder();
span.append(text);
if(isDelete) {
StrikethroughSpanstrikethroughSpan = new StrikethroughSpan();
span.setSpan(strikethroughSpan,0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (isBold){
StyleSpanboldStyle = new StyleSpan(Typeface.BOLD);
span.setSpan(boldStyle,0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
span.setSpan(newForegroundColorSpan(Color.parseColor(color)), 0,text.length(),Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
returnspan;
}
最后,项目中用到了格式化字符串,所以只能采取第一种方式来避免样式信息被清除。这里遇到一个非常奇葩的坑, fromHtml(String)无法正常显示带<strike>标签的格式。解决办法是结合使用spannable,如下:
public CharSequence renderSpan(String text,String color, boolean isBold, boolean isDelete) {
if(TextUtils.isEmpty(color)) {
color ="#272934";
}
if(TextUtils.isEmpty(text)) {
returnspan;
}
SpannableStringBuilder span = new SpannableStringBuilder();
span.append(text);
if(isDelete) {
span.insert(0, "<strike>");
span.append("</strike>");
}
if (isBold){
span.insert(0, "<b>");
span.append("</b>");
}
//span.insert(0, "<font color=/"" + color +"/">");
//span.append("</font>");
returnspan;
}
Resources res = getResources();String text = String.format(res.getString(R.string.welcome_messages),renderSpan(escapedUsername ,"",true,true));
SpannableStringBuilder OperateStr =new SpannableStringBuilder(text);
Object[]spans = operateStr.getSpans(0, operateStr.length(), Object.class);
if (spans.length > 0) {
for(Object object : spans) {
intstart = operateStr.getSpanStart(object);
intend = operateStr.getSpanEnd(object);
StrikethroughSpan strikethroughSpan = new StrikethroughSpan();
operateStr.setSpan(strikethroughSpan, start, end,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
break;
}
}
这里通过其他span对象来确定样式字符串的位置,然后采用第二种方式进行处理。新闻热点
疑难解答