Android技术知识Android开发Android开发

Android SpannableString和Spannabl

2018-09-07  本文已影响23人  zYinux

一.导引

1.适用对象

2.教程结构

二.正文

1.简介

SpannableString和SpannableStringBuilder的关系类似于String和StringBuilder。前者不可变,后者可变。所以两者的使用方法基本相同。

功能在于给一串普通的字符串加上颜色,大小背景等样式和特殊事件(点击事件)。下面先上一个例子

image

这个例子很普通,小伙伴们一看可能会觉得这不就是几个TextView吗?

没错,这就是TextView。但不是几个,而是一个,只用一个TextView显示出这串花花绿绿的文字是不是很🐂的感觉呢?

这个时候可能有小伙伴会说:“一个TextView?也简单啊,我写成html,加点color,background样式,然后用 Html.fromHtml( ) 一下还不是轻轻松松,要你这破Span啥啥的干啥用!”

没错,这样子是能实现这个效果,但是你们不觉得一串串html的代码硬编码在Android项目里很难看么!而且经过我对 Html.fromHtml( ) 的源码的研究发现,这个方法并没有什么神秘之处(能够DuangDuang的就给文字加特技,呸! 加样式)。

mSpannableStringBuilder = new SpannableStringBuilder();
if (end == start) {
                mSpannableStringBuilder.removeSpan(obj[i]);
            } else {
                mSpannableStringBuilder.setSpan(obj[i], start, end, Spannable.SPAN_PARAGRAPH);
            }

上面是截取了部分Html.fromHtml( ) 方法调用的源码。细心的小伙伴们肯定发现了,这里面出现了个SpannableStringBuilder()。所以一切真相大白了,原来该方法将html解析之后通过SpannableStringBuilder来给他添加样式。看到这的小伙伴们是不是学会用SpannableStringBuilder很有用了呢!😁

2.SpannableString
        SpannableString ss=new SpannableString("这是另外一串普通的文字");
        ForegroundColorSpan colorSpan=new ForegroundColorSpan(Color.RED);
        ss.setSpan(colorSpan,0,5,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        tv.setText(ss);

使用方法和SpannableStringBuilder类似,简单举个例子,不做过多的解释。

3.SpannableStringBuilder

本章的主角,SpannableString的好基友。

class SpannableStringBuilder implements CharSequence, GetChars, Spannable, Editable,
        Appendable, GraphicsOperations{}
//这里主要注意CharSequence和Spannable
//继承自Spannable,赋予了它给文本设定样式的基础功能
//实现接口CharSequence则代表了他能在很多地方使用,比如TextView的setText方法的参数就是CharSequence对象

下面来看主要的两个方法

    public SpannableStringBuilder append(CharSequence text) {}
    //将文本添加到SpannableStringBuilder中,和StringBuilder的append方法功能类似
    public void setSpan(Object what, int start, int end, int flags) {}

用于设置样式的核心方法。参数:

  1. what
    各种Span,不同的Span对应不同的样式,具体有如下:
  1. start
    样式生效的开始位置,包括该位置
    3)end
    样式结束的位置,不包括该位置,所以设定一串文字中前3个文字的样式时start:0,end:3。而不是end:2
  2. flags
    这几个参数中最难懂最麻烦最难搞的一个参数。
    主要有以下四个值:
        //部分代码
        final String baseString="这是开始的文字";
        SpannableStringBuilder sb;
        ForegroundColorSpan span;

        sb=new SpannableStringBuilder();
        sb.append(baseString);
        span=new ForegroundColorSpan(Color.RED);
        sb.setSpan(span,2,4,Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
        et.setText(sb);

        sb=new SpannableStringBuilder();
        sb.append(baseString);
        span=new ForegroundColorSpan(Color.RED);
        sb.setSpan(span,2,4,Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        et2.setText(sb);

        sb=new SpannableStringBuilder();
        sb.append(baseString);
        span=new ForegroundColorSpan(Color.RED);
        sb.setSpan(span,2,4,Spanned.SPAN_INCLUSIVE_INCLUSIVE);
        et3.setText(sb);

        sb=new SpannableStringBuilder();
        sb.append(baseString);
        span=new ForegroundColorSpan(Color.RED);
        sb.setSpan(span,2,4,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        et4.setText(sb);
4.激动人心的实战时刻

ForegroundColorSpan的使用:

        SpannableStringBuilder sb=new SpannableStringBuilder();
        sb.append("红色绿色蓝色");
        ForegroundColorSpan colorSpan=new ForegroundColorSpan(Color.RED);
        sb.setSpan(colorSpan,0,2,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

        colorSpan=new ForegroundColorSpan(Color.GREEN);
        sb.setSpan(colorSpan,2,4,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

        colorSpan=new ForegroundColorSpan(Color.BLUE);
        sb.setSpan(colorSpan,4,6,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

        tv.setText(sb);

效果:


image

花花绿绿的最好看了☺

ImageSpan:

        SpannableStringBuilder sb=new SpannableStringBuilder();
        sb.append("图片前面的变成图片了");
        ImageSpan span=new ImageSpan(this,R.mipmap.ic_launcher);
        sb.setSpan(span,0,2,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        //替换掉了前两个文字,所以添加的图片占用两个文字的宽度
        tv.setText(sb);

效果:


image

说好的大家一起做文字的,你却偷偷整容成图片了,哼!

ClickableSpan:

        SpannableStringBuilder sb=new SpannableStringBuilder();
        sb.append("我们中有两个文字可以点击哦");
        ClickableSpan span=new ClickableSpan() {
            @Override
            public void onClick(View widget) {
                Toast.makeText(MainActivity.this,"你点击了我",Toast.LENGTH_LONG).show();
            }
        };
        sb.setSpan(span,0,2,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        tv.setText(sb);

        //设置了点击事件后请加上这句,不然点击事件不起作用
        tv.setMovementMethod(LinkMovementMethod.getInstance());

效果:


image

别忘了这一句:tv.setMovementMethod(LinkMovementMethod.getInstance());
很重要。

另外给文字设置点击事件之后会自动给文字加上下划线,可以使用如下方式去除这个默认的下划线:

    //自定义类继承自ClickableSpan。用该类来代替使用
    public abstract class NoLineClickSpan extends ClickableSpan {
        public NoLineClickSpan() {
            super();
        }
        @Override
        public void updateDrawState(TextPaint ds) {
            /**set textColor**/
            ds.setColor(ds.linkColor);
            /**Remove the underline**/
            ds.setUnderlineText(false);
        }
        @Override
        public abstract void onClick(View widget);
    }

由于篇幅所限,在此就介绍这么多的Span使用例子,其他几个Span的适用方法还请小伙伴们自己探索,毕竟自己动手学的快嘛(我才不会说是我自己懒😕!)
另外小伙伴们是不是觉得new出一个又一个的span很麻烦呢,而且手动计算start,end很麻烦呢?下面给大家推荐一个简单的辅助类。

好了,以上都是广告时间,下面进入正文:
欢迎小伙伴使用我写的一个辅助工具类,gayhub地址:https://github.com/zYinux/SpecialString
使用了该库之后设置样式只需要:

 //构建SpecialStyle 用来设置样式的核心类
        SpecialStyle style=new SpecialStyle();
        SpecialStringBuilder sb=new SpecialStringBuilder();

        //设置文本颜色为黑色。第二个参数save的意思是代表该样式是否应用到下一段文字,如果不传则为true
        style.setColor(Color.BLACK,false);
        //为文字设置样式
        sb.append("售价:",style);

        style.setColor(Color.RED,false);
        sb.append("¥99.99  ",style);

        //设置颜色背景和点击事件样式
        //点击事件默认为不应用于下一段文字
        style.setColor(Color.GREEN,false)
             .setBackgroundColor(Color.rgb(200,200,200),false)
                .setClickable(new ClickableStyle.OnClick() {
            @Override
            public void onClick(View widget) {
                Toast.makeText(MainActivity.this,"开始抢购",Toast.LENGTH_SHORT).show();
            }
        });
        sb.append("立即抢购",style);

        //为TextView设置刚刚构建的文本
        tv.setText(sb.getCharSequence());
        //如果为文字添加了点击事件,请添加这一句,否则点击事件不生效
        tv.setMovementMethod(LinkMovementMethod.getInstance());

是不是简单了很多了呢?终于不用去理会那些烦人的start,end,flag了。具体使用方法请大家转到GitHub查看,方便的话欢迎小伙伴给个star,谢谢啦。

5.瞎逼逼时间

小伙伴们好!
我叫 zYinux ,取这个网名是为了致敬IT界的大佬的项目Linux。可惜目前我还是一个刚入门的菜鸟,希望能通过自己的努力攀爬到更高的境界。这是我写的第二篇博客,上一篇已是1年前了,接下来会努力一个月出一篇博客。文笔不好望大家见谅,希望看到这里的小伙伴已经学会了上面的知识,如果小伙伴发现了教程中有错误和遗漏之处,欢迎联系我指正。
QQ交流群:589184413

上一篇 下一篇

猜你喜欢

热点阅读