Android基础之TextView简单富文本实现


1.Html.fromHtml()

Html.fromHtml()是Android提供的简单支持部分html标签的方法。
查看Html源码可知目前支持的html标签有<br><p><font><a><big>

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 </br> for each <br>
        // so we can safely emit the linebreaks when we handle the close tag.
    } else if (tag.equalsIgnoreCase("p")) {
        startBlockElement(mSpannableStringBuilder, attributes, getMarginParagraph());
        startCssStyle(mSpannableStringBuilder, attributes);
    } else if (tag.equalsIgnoreCase("ul")) {
        startBlockElement(mSpannableStringBuilder, attributes, getMarginList());
    } else if (tag.equalsIgnoreCase("li")) {
        startLi(mSpannableStringBuilder, attributes);
    } else if (tag.equalsIgnoreCase("div")) {
        startBlockElement(mSpannableStringBuilder, attributes, getMarginDiv());
    } else if (tag.equalsIgnoreCase("span")) {
        startCssStyle(mSpannableStringBuilder, attributes);
    } 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")) {
        startBlockquote(mSpannableStringBuilder, attributes);
    } 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("del")) {
        start(mSpannableStringBuilder, new Strikethrough ());
    } else if (tag.equalsIgnoreCase("s")) {
        start(mSpannableStringBuilder, new Strikethrough ());
    } else if (tag.equalsIgnoreCase("strike")) {
        start(mSpannableStringBuilder, new Strikethrough ());
    } 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') {
        startHeading(mSpannableStringBuilder, attributes, tag.charAt(1) - '1');
    } else if (tag.equalsIgnoreCase("img")) {
        startImg(mSpannableStringBuilder, attributes, mImageGetter);
    } else if (mTagHandler != null) {
        mTagHandler.handleTag(true, tag, mSpannableStringBuilder, mReader);
    }
}

使用也比较简单,示例如下:

// 字体样式标签使用
String txt1 = "1.设置字体颜色<font color='red'>字体颜色改变部分1</font>和<font color='#FF8000'>字体颜色改变部分2</font>" +
"<br>2.下划线 <font color='#FF8000'><u> 下划线 </u></font>、<s>删除线</s>、<i> 斜体 </i>和<b> 粗体 </b>";
/**
 * Api24以上需要传入flags,24之前不需要传。
 */
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
    tv1.setText(Html.fromHtml(txt1, Html.FROM_HTML_MODE_LEGACY));
} else {
    tv1.setText(Html.fromHtml(txt1));
}

// 字体规格标签使用
String txt2 = "3.改变字体大小 <font color='#FF8000'><big>字体变<big>大部分</big></big></font> 和 <small>字体变小部分</small>";
tv2.setText(Html.fromHtml(txt2));

// 段落标签使用
String txt3 = "4.段落使用展示<p>段落内容展示一</P><p>段落内容展示二</P><p>段落内容展示三</P>";
tv3.setText(Html.fromHtml(txt3));

// 超链接标签使用
String txt4 = "4.测试地址信息 <a href='https://github.com/alibaba/ARouter'>【阿里出品】帮助 Android App 进行组件化改造的路由框架</a>";
// 设置后点击超链接会向外部跳转
tv4.setMovementMethod(LinkMovementMethod.getInstance());
tv4.setText(Html.fromHtml(txt4));

2.SpannableString

Html.fromHtml()虽然可以实现简单富文本的展示,但是支持的html标签有限,所以我们还可以使用SpannableString来实现更多富文本的展示方式。

  • 字体颜色、背景

    SpannableString ts1 = new SpannableString("1.设置字体颜色改变部分1改变部分2背景色");
    ts1.setSpan(new ForegroundColorSpan(Color.RED),
    8, 13, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    ts1.setSpan(new ForegroundColorSpan(Color.BLUE),
    13, 18, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    ts1.setSpan(new BackgroundColorSpan(Color.RED),
    18, 21, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    tv5.setText(ts1);
    
  • 下划线、删除线、斜体和粗体

    SpannableString ts2 = new SpannableString("2.下划线、删除线、斜体、粗体、粗斜体");
    ts2.setSpan(new UnderlineSpan(),
    2, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    ts2.setSpan(new StrikethroughSpan(),
    6, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    ts2.setSpan(new StyleSpan(Typeface.ITALIC),
    10, 12, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    ts2.setSpan(new StyleSpan(Typeface.BOLD),
    13, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    ts2.setSpan(new StyleSpan(Typeface.BOLD_ITALIC),
    16, 19, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    tv6.setText(ts2);
    
  • 上标、下标

    SpannableString ts3 = new SpannableString("3.上标1、下标2");
    ts3.setSpan(new SuperscriptSpan(), 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    ts3.setSpan(new SubscriptSpan(), 8, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    tv7.setText(ts3);
    
  • 字体大小

     // 第二个参数boolean dip,如果为true,表示前面的字体大小单位为dip,否则为像素,同上。
            SpannableString ts4 = new SpannableString("4.设置字体大小、字体大小、字体大小和字体大小");
            ts4.setSpan(new AbsoluteSizeSpan(20), 4, 8, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            ts4.setSpan(new AbsoluteSizeSpan(20, true), 9, 13, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            //设置字体大小(相对值,单位:像素) 参数表示为默认字体大小的多少倍
            // 0.5f表示默认字体大小的一半
            // 1.5f表示默认字体大小的两倍
            ts4.setSpan(new RelativeSizeSpan(0.5f), 14, 18, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            ts4.setSpan(new RelativeSizeSpan(1.5f), 19, 23, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            tv8.setText(ts4);
    
  • 电话、网络、短信

    SpannableString ts5 = new SpannableString("5.打电话\n百度地址\n短信发送");
    ts5.setSpan(new URLSpan("tel:123456789"), 2, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    ts5.setSpan(new URLSpan("http://www.baidu.com"), 5, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    ts5.setSpan(new URLSpan("sms:123456789"), 9, 13, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    // 设置可点击
    tv9.setMovementMethod(LinkMovementMethod.getInstance());
    tv9.setText(ts5);
    
  • 图片

    SpannableString ts6 = new SpannableString("6.在文本中添加表情(表情)");
    Drawable drawable = getResources().getDrawable(R.mipmap.ic_launcher);
    drawable.setBounds(0, 0, 42, 42);
    ImageSpan imageSpan = new ImageSpan(drawable);
    ts6.setSpan(imageSpan, 8, 10, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
    tv10.setText(ts6);
    
  • 点击事件

    SpannableString ts7 = new SpannableString("请仔细阅读相关协议,若注册软件,代表你已同意注册协议和隐私政策");
    //设置点击事件
    ts7.setSpan(new Clickable(registerClickListener), 22, 26,
    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    ts7.setSpan(new Clickable(privacyListener), 27, 31,
    Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    tv11.setText(ts7);
    tv11.setMovementMethod(LinkMovementMethod.getInstance());
    
    private View.OnClickListener registerClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(TextViewActivity.this, "注册协议", Toast.LENGTH_SHORT).show();
        }
    };
    private View.OnClickListener privacyListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(TextViewActivity.this, "隐私政策", Toast.LENGTH_SHORT).show();
        }
    };
    
    class Clickable extends ClickableSpan {
        private final View.OnClickListener mListener;
    
        public Clickable(View.OnClickListener l) {
            mListener = l;
        }
    
        /**
         * 重写父类点击事件
         */
        @Override
        public void onClick(View v) {
            mListener.onClick(v);
        }
    
        /**
         * 重写父类updateDrawState方法 我们可以给TextView设置字体颜色,背景颜色等等...
         */
        @Override
        public void updateDrawState(TextPaint ds) {
            ds.setColor(getResources().getColor(R.color.colorPrimary));
        }
    }
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值