您的位置:首页 > 产品设计 > UI/UE

SpannableString&SpannableStringBuilder一些简单介绍

2017-06-09 23:42 549 查看

开始

最近还是挺忙的,改公司各种bug,添加新的功能,这不,有个新的功能如下:


上面的两个人昵称wuguang,rozbo是可以点击进入各自的用户信息界面的,刚开始第一感觉是使用Html.from(string)去做,后来发现颜色上是对了,就是点击事件不太好写,在前辈的教育下新解锁了SpannableString技能。

以前也用过SpannableString,但是没有深入的学习,现在发现有时间,就好好的看一下。先不说这玩意儿是干嘛的,其实我也听懵逼的,因为andorid这玩意东西太多了,那么就看功能,然后再慢慢说吧:









这就是一个TextView借助SpannableString实现的,就像Google官方文档介绍的一样:

This is the class for text whose content and markup can both be changed.

意思是内容和标记都可以更改的类。

SpannableString&SpannableStringBuilder

这两个类就像String与StringBuilder一样,一个内容是不可变的,一个是可变的(SpannableStringBuilder也是通过append进行拼接的)。SpannableString与SpannableStringBuilder都实现了CharSequence接口,所以他们都可以在TextView中直接使用。

SpannableString与SpannableStringBuilder的使用方法类似,最主要的方法算是:

public void setSpan(Object what, int start, int end, int flags) {
super.setSpan(what, start, end, flags);
}


这里的what就是我们要实现的span,也就是我们需要的各种效果。start,end,flags等会再谈,先看android给我们提供的各种效果:



大致可以分为:

1.BackgroundColorSpan/ForegroundColorSpan: 背景/前景效果,类似于这种效果:



简单代码如下:

SpannableString ss = new SpannableString(msg);
BackgroundColorSpan colorSpan = new BackgroundColorSpan(Color.BLUE);
ss.setSpan(colorSpan,3,6, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
mTvView.setText(ss);


2.可点击的span:URLSpan与ClickableSpan,URLSpan是继承自ClickableSpan,实现了onClick方法,基本效果如下:



简单代码如下:

SpannableString ss = new SpannableString(msg);
ClickableSpan span = new ClickableSpan() {
@Override
public void onClick(View widget) {
Toast.makeText(MainActivity.this, ">>>click me>>>", Toast.LENGTH_SHORT).show();
}
};
ss.setSpan(span,0,5,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

mTvView.setText(ss);
mTvView.setMovementMethod(LinkMovementMethod.getInstance());


3.改变字符大小,样式,排列型的span,包括以下几个:

a.

可更改字体的TypefaceSpan, 目前example里面可以选择的字体有:monospace”, “serif”, and “sans-serif”. 但是个人感觉不太明显,所以感觉没什么卵用。

b

.基于X轴缩放的span:



代码如下:

SpannableString ss = new SpannableString(msg);
//放大5.2倍
ScaleXSpan xspan = new ScaleXSpan(5.2f);
ss.setSpan(xspan,1,5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
mTvView.setText(ss);


既然有基于X轴缩放的,那有没有关于y轴缩放的呢?答案是没有啊,至于原因我表示也不清楚,大家自行脑补吧。

c.

RelativeSizeSpan&AbsouluteSizeSpan 相对大小与绝对大小。

//相对字体的1.5倍的大小



//绝对大小20dip的字体



d.

SuperscriptSpan&SubcriptSpan 应用于数字公式或者模型中的上下标:



大致代码为:

String str = "(X1 + X2)2 = X12+X22+2X1X2" ;
SpannableString ss = new SpannableString(str);

//设置下标
ss.setSpan(new SubscriptSpan(),2,3,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.setSpan(new SubscriptSpan(),7,8,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

//设置上标
ss.setSpan(new SuperscriptSpan(),9,10,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

ss.setSpan(new SubscriptSpan(),14,15,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.setSpan(new SuperscriptSpan(),15,16,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

ss.setSpan(new SubscriptSpan(),18,19,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.setSpan(new SuperscriptSpan(),19,20,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

ss.setSpan(new SubscriptSpan(),23,24,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.setSpan(new SubscriptSpan(),25,26,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

mTvView.setText(ss);


e.

StyleSpan&TextAppearanceSpan

前者可以控制字体是否粗体,是否斜体,是否bold_italic

后者则通过自己设置的R.style.my_style控制字体大小,颜色等样式





4.其他效果的span:

a.

MaskFilterSpan 修饰效果的span,andorid本身提供了两种效果:模糊和浮雕效果:





但是这里需要关闭硬件加速,否则看不出来效果,具体参数可以参考

5.UnderLineSpan&StrikethroughSpan 这个就不解释了,分别是我们的下划线span和删除线span:





关于flag参数

不管是SpannableString和SpannableStringBuilder,都是有个方法:

public void setSpan(Object what, int start, int end, int flags) ;


其中最后一个参数,这个flags对SpannableString没有作用(亲测过),因为SpannableString像String一样,是不变的,没法改变内容,即使你传入0也无所谓。

但是对于SpannableStringBuilder就不一样了,它有个四个参数值:

Spannable.SPAN_INCLUSIVE_INCLUSIVE
Spannable.SPAN_INCLUSIVE_EXCLUSIVE ;
Spannable.SPAN_EXCLUSIVE_INCLUSIVE;
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;


我么大概知道,INCLUSIVE是包含的意思,而EXCLUSIVE就是不包含的意思,那么上面的就可以非常简单的理解为数学中是否包含了:

[A,B];  //左右都包含
[A,B);  //左包含 右不包含
(A,B];  //左不包含,右包含
(A,B);  //左右都不包含


而这里的A,B就是我们setSpan中的start和end参数了。具体什么意思,我们来举个例子:



我们在start=3,end=8的地方设置了下划线span,模式为Spanned.SPAN_EXCLUSIVE_EXCLUSIVE【也就是两边都不包括】,代码如下:

mTv = (TextView) findViewById(R.id.id_tv);
mSpannableBuilder = new SpannableStringBuilder("1234567890张三Tom");
UnderlineSpan span = new UnderlineSpan();
mSpannableBuilder.setSpan(span,3,8,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setText(mSpannableBuilder);


现在在index=3处插入数据:

mSpannableBuilder.insert(3,"hello");
mTv.setText(mSpannableBuilder);


我们看到是这样的:



我们可以看到我们的hello没有应用到下划线的。

现在把flag换成SPAN_INCLUSIVE_INCLUSIVE试一下

mSpannableBuilder = new SpannableStringBuilder("1234567890张三Tom");
UnderlineSpan span = new UnderlineSpan();
mSpannableBuilder.setSpan(span,3,8,Spanned.SPAN_INCLUSIVE_INCLUSIVE);
mTv.setText(mSpannableBuilder);


还是在index=3的地方插入:

mSpannableBuilder.insert(3,"hello");
mTv.setText(mSpannableBuilder);




我们看到了hello也被添加了下划线。

那么这个flag就表明了在start和end区间里,span的应用情况。如果insert的index在这个区间内,那么插入的数据也会被应用到该sapn效果中了。

基本上就是这里了。改洗洗睡了。

代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: