安卓开发中TextView 是我们最常用的控件之一,我们用TextView为我们在页面中展示文本。展示普通文本当然没有任何难度,使用TextView的setText()方法设置一个字符串就可以了,但是当我们需要在文本中展示不同格式文本的时候,设置普通的字符串就不行了。那该怎么办?当然就说到我们今天的主角了。SpannableString和SpannableStringBuilder
SpannableString和String一样都是一种字符串类型,他们都实现了CharSequence,所以SpannableString也可以直接使用TextView的setText()方法设置文本。SpannableString的特别之处就在于SpannableString可以打造丰富多彩的文本显示效果。SpannableString可以通过使用其方法setSpan()实现字符串各种形式风格的显示,重要的是可以指定设置的区间,也就是为字符串指定下标区间内的子字符串设置格式。
可以轻松实现以下效果:
自定义文本中文字的字体大小(包括绝对大小和相对大小,区别看下面解释)
设置文本中文字的前景色、背景色
为文本中的文字设置下划线,删除线
设置文本中的内容上标、下标
为文字设置风格,粗体斜体等
设置图文混排,即文字中添加图片
可以为部分文本设置点击事件
以上是一些常用的效果,并不是全部。
下面说一下怎么实现这些效果。
SpannableString有一个方法叫做setSpan(),我们就是用这个方法来实现不同展示效果的。
这个方法如下所示:
public void setSpan(Object what, int start, int end, int flags) {
super.setSpan(what, start, end, flags);
}
setSpan()方法有四个参数,其中what就是所要设置的格式,start是需要设置格式的子字符串的起始下标,end就是结束下标,但并不包括这个位置。flag一共有四种值可选。如下:
这里先看一个SpannableString的简单实现:
TextView main_tv=findViewById(R.id.main_tv);
SpannableString ss=new SpannableString("其实我是一个好人");
ForegroundColorSpan foregroundColorSpan=new ForegroundColorSpan(Color.parseColor("#FF0000"));
ss.setSpan(foregroundColorSpan,2,6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
main_tv.setText(ss);
上述代码实现的效果是:
SpannableString的setSpan()方法可以同时使用多个,实现多种效果叠加。
setSpan()方法中的what是最重要的一个参数,对应各种span,不同的span对应不同的样式。接下来我们就来看一下不同的几种常见的span以及效果。
为文本设置背景色 BackgroundColorSpan
代码如下:
TextView main_tv=findViewById(R.id.main_tv);
SpannableString ss=new SpannableString("其实我是一个好人");
ackgroundColorSpan backgroundColorSpan=new BackgroundColorSpan(Color.parseColor("#FFFF00"));
ss.setSpan(backgroundColorSpan,2,6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
main_tv.setText(ss);
效果如图:
为文本设置下划线以及删除线
UnderlineSpan:下划线
StrikethroughSpan :删除线
代码示例:
TextView main_tv=findViewById(R.id.main_tv);
SpannableString ss=new SpannableString("其实我是一个好人");
UnderlineSpan underlineSpan=new UnderlineSpan();//下划线span
StrikethroughSpan strikethroughSpan=new StrikethroughSpan();//删除线
ss.setSpan(underlineSpan,3,6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.setSpan(strikethroughSpan,0,3,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
main_tv.setText(ss);
效果展示:
设置文本字体 AbsoluteSizeSpan (设置的是绝对大小,直接用具体数值指定文字大小)
代码:
TextView main_tv=findViewById(R.id.main_tv);
SpannableString ss=new SpannableString("其实我是一个好人");
AbsoluteSizeSpan absoluteSizeSpan=new AbsoluteSizeSpan(30,true);
ss.setSpan(absoluteSizeSpan,3,6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
main_tv.setText(ss);
效果如图:
设置文本字体 RelativeSizeSpan(设置的是相对大小,在TextView原有的文字大小的基础上,相对设置文字大小)
代码如下:
TextView main_tv=findViewById(R.id.main_tv);
SpannableString ss=new SpannableString("其实我是一个好人");
RelativeSizeSpan relativeSizeSpan=new RelativeSizeSpan(0.5f);
ss.setSpan(relativeSizeSpan,3,6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
main_tv.setText(ss);
效果:
设置字体样式(粗体、斜体等) StyleSpan
代码:
TextView main_tv=findViewById(R.id.main_tv);
SpannableString ss=new SpannableString("其实我是一个好人");
StyleSpan styleSpan=new StyleSpan(Typeface.BOLD);
ss.setSpan(styleSpan,3,6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
main_tv.setText(ss);
效果:
设置文本中的内容上标 SuperscriptSpan 、下标SubscriptSpan
代码:
TextView main_tv=findViewById(R.id.main_tv);
SpannableString ss=new SpannableString("其实我是一个好人");
SuperscriptSpan superscriptSpan=new SuperscriptSpan();//上标
SubscriptSpan subscriptSpan=new SubscriptSpan();//下标
//ss.setSpan(superscriptSpan,3,5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss.setSpan(subscriptSpan,0,2,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
main_tv.setText(ss);
TextView main_tv=findViewById(R.id.main_tv);
SpannableString ss=new SpannableString("其实我是一个好人");
ImageSpan imageSpan=new ImageSpan(this,R.mipmap.ic_launcher);
ss.setSpan(imageSpan,2,3,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
main_tv.setText(ss);
代码:
TextView main_tv=findViewById(R.id.main_tv);
SpannableString ss=new SpannableString("其实我是一个好人");
ClickableSpan clickableSpan=new ClickableSpan() {
@Override
public void onClick(View widget) {
Toast.makeText(SecondActivity.this, "点击了", Toast.LENGTH_SHORT).show();
}
};
ss.setSpan(clickableSpan,2,4,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
main_tv.setText(ss);
main_tv.setMovementMethod(LinkMovementMethod.getInstance());
使用ClickableSpan设置点击事件,最后还需要加上main_tv.setMovementMethod(LinkMovementMethod.getInstance())这一句,不然不生效。
SpannableStringBuilder 与 SpannableString 的区别就和string 与 stringBuilder 的区别类似。就是SpannableStringBuilder可以使用append()方法拼接,而SpannableString不可拼接。其他没有多大区别。
以上简单总结了一下SpannableStringBuilder和SpannableString的用法,只是一些常用的用法,还有很多东西有待学习。