SpannableString、SpannableStringBuilder与String的关系
1.1 概述
SpannableString、SpannableStringBuilder基本上与String差不多,也是用来存储字符串,但它们俩的特殊就在于有一个SetSpan()函数,能给这些存储的String添加各种格式或者称样式(Span),将原来的String以不同的样式显示出来,比如在原来String上加下划线、加背景色、改变字体颜色、用图片把指定的文字给替换掉,等等。所以,总而言之,SpannableString、SpannableStringBuilder与String一样, 首先也是传字符串,但SpannableString、SpannableStringBuilder可以对这些字符串添加额外的样式信息,但String则不行。
它们的区别在于 SpannableString像一个String一样,构造对象的时候传入一个String,之后再无法更改String的内容,也无法拼接多个 SpannableString;而SpannableStringBuilder则更像是StringBuilder,它可以通过其append()方法来拼接多个String。
| 功能 | String |SpannableString | SpannableStringBuilder|
|–|–|–|–|–|
| 存储字符串 | 是 | 是 | 是 |
| 通过setSpan()能给存储的字符串添加各种样式(Span),比如颜色背景等 | 否 | 是 | 是 |
| 创建之后是否可以更改其内容并跟随变化 | 否 | 否 | 是
1.2 setSpan()方法介绍
void setSpan (Object what, int start, int end, int flags)
Object what | 对应各种Span |
int start | 开始应用指定Span的位置,索引从0开始 |
int end | 结束应用指定Span的位置,特效并不包括这个位置 |
int flags | 指定范围前后输入新的字符时,会不会应用效果 |
flags参数介绍
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE | 前后都不包括,即在指定范围的前面和后面插入新字符都不会应用新样式 |
Spannable.SPAN_EXCLUSIVE_INCLUSIVE | 前面不包括,后面包括,即仅在范围字符的后面插入新字符时会应用新样式 |
Spannable.SPAN_INCLUSIVE_EXCLUSIVE | 前面包括,后面不包括 |
Spannable.SPAN_INCLUSIVE_INCLUSIVE | 前后都包括 |
1.3 Span汇总
用途 | Span |
设置字体颜色 | ForegroundColorSpan |
设置字体背景颜色 | BackgroundColorSpan |
设置字体大小 | AbsoluteSizeSpan |
设置字体为粗体、斜体 | StyleSpan |
设置字体删除线 | StrikethroughSpan |
设置字体下划线 | UnderlineSpan |
将文字替换成图片 | ImageSpan |
点击文字可以打开一个URL | URLSpan |
文字可点击 | ClickableSpan |
… | … |
1.3.1 设置字体颜色 ForegroundColorSpan
String str = "Hello World!";
SpannableStringBuilder ssb = new SpannableStringBuilder(str);
ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(ContextCompat.getColor(this, R.color.colorAccent));
ssb.setSpan(foregroundColorSpan, 0, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setText(ssb);
1.3.2 点击文字可以打开一个URL URLSpan
String str = "点击百度!";
SpannableStringBuilder ssb = new SpannableStringBuilder(str);
URLSpan urlSpan = new URLSpan("https://www.baidu.com/");
ssb.setSpan(urlSpan, 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setMovementMethod(LinkMovementMethod.getInstance());
mTv.setText(ssb);
1.3.3 将文字替换成图片 ImageSpan
String str = "img ImageSpan!";
SpannableStringBuilder ssb = new SpannableStringBuilder(str);
ImageSpan imageSpan = new ImageSpan(this,R.mipmap.ic_launcher, ImageSpan.ALIGN_BOTTOM);
ssb.setSpan(imageSpan, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setText(ssb);
1.3.4 文字可点击 ClickableSpan
String str = "点击事件 ImageSpan!";
SpannableStringBuilder ssb = new SpannableStringBuilder(str);
MClickableSpan mClickableSpan = new MClickableSpan(new MClickableSpan.OnClickListener() {
@Override
public void OnClick(View view) {
Toast.makeText(MainActivity.this, "点击事件", Toast.LENGTH_SHORT).show();
}
});
ssb.setSpan(mClickableSpan, 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// 凡是有要执行的动作,都必须设置MovementMethod对象
mTv.setMovementMethod(LinkMovementMethod.getInstance());
mTv.setHighlightColor(ContextCompat.getColor(this, R.color.colorAccent));
mTv.setText(ssb);
static class MClickableSpan extends ClickableSpan {
private OnClickListener onClickListener;
interface OnClickListener {
void OnClick(View view);
}
public MClickableSpan(OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
ds.setColor(0xFF5394f5);
ds.setUnderlineText(false);
ds.clearShadowLayer();
ds.bgColor = Color.TRANSPARENT;
}
@Override
public void onClick(@NonNull View widget) {
onClickListener.OnClick(widget);
}
}
参考资料
SpannableString与SpannableStringBuilderAndroid中span总结
TextView显示丰富多彩的文字(一)TextView显示丰富多彩的文字(二)TextView显示丰富多彩的文字(三)