1、SpannableString、SpannableStringBuilder与String的关系
首先SpannableString、SpannableStringBuilder基本上与String差不多,也是用来存储字符串,但它们俩的特殊就在于有一个SetSpan()函数,能给这些存储的String添加各种格式或者称样式(Span),将原来的String以不同的样式显示出来,比如在原来String上加下划线、加背景色、改变字体颜色、用图片把指定的文字给替换掉,等等。所以,总而言之,SpannableString、SpannableStringBuilder与String一样, 首先也是传字符串,但SpannableString、SpannableStringBuilder可以对这些字符串添加额外的样式信息,但String则不行。
注意:如果这些额外信息能被所用的方式支持,比如将SpannableString传给TextView;也有对这些额外信息不支持的,比如前一章讲到的Canvas绘制文字,对于不支持的情况,SpannableString和SpannableStringBuilder就是退化为String类型,直接显示原来的String字符串,而不会再显示这些附加的额外信息。
2、SpannableString与SpannableStringBuilder区别
它们的区别在于 SpannableString像一个String一样,构造对象的时候传入一个String,之后再无法更改String的内容,也无法拼接多个 SpannableString;而SpannableStringBuilder则更像是StringBuilder,它可以通过其append()方法来拼接多个String;
3、SetSpan()
void setSpan (Object what, int start, int end, int flags)
函数意义:给SpannableString或SpannableStringBuilder特定范围的字符串设定Span样式,可以设置多个(比如同时加上下划线和删除线等),Falg参数标识了当在所标记范围前和标记范围后紧贴着插入新字符时的动作,即是否对新插入的字符应用同样的样式。
参数说明:
object what :对应的各种Span,后面会提到;
int start:开始应用指定Span的位置,索引从0开始
int end:结束应用指定Span的位置,特效并不包括这个位置。比如如果这里数为3(即第4个字符),第4个字符不会有任何特效。从下面的例子也可以看出来。
int flags:取值有如下四个
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE:前后都不包括,即在指定范围的前面和后面插入新字符都不会应用新样式
Spannable.SPAN_EXCLUSIVE_INCLUSIVE :前面不包括,后面包括。即仅在范围字符的后面插入新字符时会应用新样式
Spannable.SPAN_INCLUSIVE_EXCLUSIVE :前面包括,后面不包括。
Spannable.SPAN_INCLUSIVE_INCLUSIVE :前后都包括。
下面写了个小demo,先看一下效果图:
public
class
MainActivity
extends
Activity
implements
OnClickListener {
private
TextView tv;
private
Button underline_btn;
private
Button strike_btn;
private
Button style_btn;
private
Button font_btn;
private
Button color_btn1;
private
Button color_btn2;
private
Button url_btn;
private
Button image_btn;
private
Button maskfilte_btn;
private
Button Rasterizer_btn;
private
Button spannablestringbuilder;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView)
this
.findViewById(R.id.tv);
underline_btn = (Button)
this
.findViewById(R.id.underline_btn);
strike_btn = (Button)
this
.findViewById(R.id.strike_btn);
style_btn = (Button)
this
.findViewById(R.id.style_btn);
font_btn = (Button)
this
.findViewById(R.id.font_btn);
color_btn1 = (Button)
this
.findViewById(R.id.color_btn1);
color_btn2 = (Button)
this
.findViewById(R.id.color_btn2);
url_btn = (Button)
this
.findViewById(R.id.url_btn);
image_btn = (Button)
this
.findViewById(R.id.image_btn);
maskfilte_btn = (Button)
this
.findViewById(R.id.maskfilte_btn);
Rasterizer_btn = (Button)
this
.findViewById(R.id.Rasterizer_btn);
spannablestringbuilder = (Button)
this
.findViewById(R.id.spannablestringbuilder);
underline_btn.setOnClickListener(
this
);
strike_btn.setOnClickListener(
this
);
style_btn.setOnClickListener(
this
);
font_btn.setOnClickListener(
this
);
color_btn1.setOnClickListener(
this
);
color_btn2.setOnClickListener(
this
);
url_btn.setOnClickListener(
this
);
image_btn.setOnClickListener(
this
);
maskfilte_btn.setOnClickListener(
this
);
Rasterizer_btn.setOnClickListener(
this
);
spannablestringbuilder.setOnClickListener(
this
);
}
@Override
public
void
onClick(View v) {
switch
(v.getId()) {
case
R.id.underline_btn:
addUnderLineSpan();
break
;
case
R.id.strike_btn:
addStrikeSpan();
break
;
case
R.id.style_btn:
addStyleSpan();
break
;
case
R.id.font_btn:
addFontSpan();
break
;
case
R.id.color_btn1:
addForeColorSpan();
break
;
case
R.id.color_btn2:
addBackColorSpan();
break
;
case
R.id.url_btn:
addUrlSpan();
break
;
case
R.id.image_btn:
addImageSpan();
break
;
case
R.id.maskfilte_btn:
addmaskfilteSpan();
break
;
case
R.id.Rasterizer_btn:
addRasterizerSpan();
break
;
case
R.id.spannablestringbuilder:
addspannablestringbuilderSpan();
break
;
}
}
/**
* spannablestringbuilder
*/
private
void
addspannablestringbuilderSpan() {
SpannableStringBuilder ss=
new
SpannableStringBuilder(
"红色超链接斜体删除线绿色下划线图片:."
);
//用颜色标记文本
ss.setSpan(
new
ForegroundColorSpan(Color.RED),
0
,
2
,
//setSpan时需要指定的 flag,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE(前后都不包括).
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//用超链接标记文本
ss.setSpan(
new
URLSpan(
"tel:4155551212"
),
2
,
5
,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//用样式标记文本(斜体)
ss.setSpan(
new
StyleSpan(Typeface.BOLD_ITALIC),
5
,
7
,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//用删除线标记文本
ss.setSpan(
new
StrikethroughSpan(),
7
,
10
,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//用下划线标记文本
ss.setSpan(
new
UnderlineSpan(),
10
,
16
,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//用颜色标记
ss.setSpan(
new
ForegroundColorSpan(Color.GREEN),
10
,
12
,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//获取Drawable资源
Drawable d = getResources().getDrawable(R.drawable.ic_launcher);
d.setBounds(
0
,
0
, d.getIntrinsicWidth(), d.getIntrinsicHeight());
//创建ImageSpan
ImageSpan span =
new
ImageSpan(d, ImageSpan.ALIGN_BASELINE);
//用ImageSpan替换文本
ss.setSpan(span,
18
,
19
, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
tv.append(
"\n"
);
tv.setText(ss);
tv.setMovementMethod(LinkMovementMethod.getInstance());
//实现文本的滚动
}
/*
* Spannable.SPAN_EXCLUSIVE_EXCLUSIVE:前后都不包括,即在指定范围的前面和后面插入新字符都不会应用新样式
* Spannable.SPAN_EXCLUSIVE_INCLUSIVE :前面不包括,后面包括。即仅在范围字符的后面插入新字符时会应用新样式
* Spannable.SPAN_INCLUSIVE_EXCLUSIVE :前面包括,后面不包括。
* Spannable.SPAN_INCLUSIVE_INCLUSIVE :前后都包括。
*/
/**
* 光栅效果
*/
private
void
addRasterizerSpan() {
SpannableString spanText =
new
SpannableString(
"StrikethroughSpan"
);
spanText.setSpan(
new
StrikethroughSpan(),
0
,
7
, Spannable.
SPAN_INCLUSIVE_EXCLUSIVE);
tv.append(
"\n"
);
tv.append(spanText);
}
/**
* 修饰效果
*/
private
void
addmaskfilteSpan() {
SpannableString spanText =
new
SpannableString(
"benzlocke6666666"
);
int
length = spanText.length();
//模糊(BlurMaskFilter)
MaskFilterSpan maskFilterSpan =
new
MaskFilterSpan(
new
BlurMaskFilter(
3
, Blur.OUTER));
spanText.setSpan(maskFilterSpan,
0
, length -
10
, Spannable.
SPAN_INCLUSIVE_EXCLUSIVE);
//浮雕(EmbossMaskFilter)
maskFilterSpan =
new
MaskFilterSpan(
new
EmbossMaskFilter(
new
float
[]{
1
,
1
,
3
},
1
.5f,
8
,
3
));
spanText.setSpan(maskFilterSpan, length -
10
, length, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
tv.append(
"\n"
);
tv.append(spanText);
}
/**
* 超链接
*/
private
void
addUrlSpan() {
SpannableString spanString =
new
SpannableString(
"超链接"
);
URLSpan span =
new
URLSpan(
"tel:0123456789"
);
spanString.setSpan(span,
0
,
3
, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(
"\n"
);
tv.append(spanString);
tv.setMovementMethod(LinkMovementMethod.getInstance());
}
/**
* 文字背景颜色
*/
private
void
addBackColorSpan() {
SpannableString spanString =
new
SpannableString(
"文字背景颜色"
);
BackgroundColorSpan span =
new
BackgroundColorSpan(Color.YELLOW);
spanString.setSpan(span,
0
,
6
, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(
"\n"
);
tv.append(spanString);
}
/**
* 文字颜色
*/
private
void
addForeColorSpan() {
SpannableString spanString =
new
SpannableString(
"文字颜色"
);
ForegroundColorSpan span =
new
ForegroundColorSpan(Color.BLUE);
spanString.setSpan(span,
0
,
4
, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(
"\n"
);
tv.append(spanString);
}
/**
* 字体大小
*/
private
void
addFontSpan() {
SpannableString spanString =
new
SpannableString(
"36号字体"
);
AbsoluteSizeSpan span =
new
AbsoluteSizeSpan(
36
);
spanString.setSpan(span,
0
,
5
, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(
"\n"
);
tv.append(spanString);
}
/**
* 粗体,斜体
*/
private
void
addStyleSpan() {
SpannableString spanString =
new
SpannableString(
"ABCDEF"
);
StyleSpan span =
new
StyleSpan(Typeface.BOLD_ITALIC);
spanString.setSpan(span,
0
,
3
, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(
"\n"
);
tv.append(spanString);
}
/**
* 删除线
*/
private
void
addStrikeSpan() {
SpannableString spanString =
new
SpannableString(
"删除线"
);
StrikethroughSpan span =
new
StrikethroughSpan();
spanString.setSpan(span,
0
,
3
, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(
"\n"
);
tv.append(spanString);
}
/**
* 下划线
*/
private
void
addUnderLineSpan() {
SpannableString spanString =
new
SpannableString(
"下划线"
);
UnderlineSpan span =
new
UnderlineSpan();
spanString.setSpan(span,
0
,
3
, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(
"\n"
);
tv.append(spanString);
}
/**
* 图片
*/
private
void
addImageSpan() {
SpannableString spanString =
new
SpannableString(
" "
);
Drawable d = getResources().getDrawable(R.drawable.ic_launcher);
d.setBounds(
0
,
0
, d.getIntrinsicWidth(), d.getIntrinsicHeight());
ImageSpan span =
new
ImageSpan(d, ImageSpan.ALIGN_BASELINE);
spanString.setSpan(span,
0
,
1
, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.append(
"\n"
);
tv.append(spanString);
}
}