如何实现多样式富文本?

项目中需要使用富文本来显示消息通知,由于消息的类型多达几十种,且这些不同类型消息显示的文案由服务端控制,这里文案需要使用富文本来显示不同颜色、大小、字体的文字,所幸是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="...">设置字体大小从17,颜色使用名字或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 &lt;b>%2$d newmessages&lt;/b>.</string>
</resources>

在这个带格式的字符串中,添加了 <b> 元素。请注意,开括号使用 &lt; 表示法进行了 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对象来确定样式字符串的位置,然后采用第二种方式进行处理。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值