开始
最近还是挺忙的,改公司各种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效果中了。
基本上就是这里了。改洗洗睡了。