转至:http://blog.it985.com/14433.html
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,先看一下效果图:
代码如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
|
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);
}
}
|
转至:http://www.thinksaas.cn/group/topic/203036/
EditText:
通常用于显示文字,但有时候也需要在文字中夹杂一些图片,比如QQ中就可以使用表情图片,又比如需要的文字高亮显示等等,如何在android中也做到这样呢?
记得android中有个android.text包,这里提供了对文本的强大的处理功能。
添加图片主要用SpannableString和ImageSpan类:
- Drawable drawable = getResources().getDrawable(id);
- drawable.setBounds(0, 0,
- drawable.getIntrinsicWidth(),
- drawable.getIntrinsicHeight());
- //需要处理的文本,[smile]是需要被替代的文本
- SpannableString spannable = new SpannableString(getText().toString()
- +"[smile]");
- //要让图片替代指定的文字就要用ImageSpan
- ImageSpan span = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);
- //开始替换,注意第2和第3个参数表示从哪里开始替换到哪里替换结束(start和end)
- //最后一个参数类似数学中的集合,[5,12)表示从5到12,包括5但不包括12
- spannable.setSpan(span, getText().length(),getText().length()
- +"[smile]".length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
- setText(spannable);
有的时候可能只想用一个textview来表示文字,但文字里肯定有分不同内容的东西,需要用不同的颜色、样式来表示.
这个时候,就需要用到SpannableString对象来处理。
- /**
- * new StrikethroughSpan() //设置删除线
- * new URLSpan("http://www.baidu.com")//http超链接
- * new URLSpan("tel:4155551212")//电话超链接
- */
- mTextView = (TextView)findViewById(R.id.test);
- SpannableString tSS = new SpannableString(“SpannableString学习中”);
- tSS.setSpan(new BackgroundColorSpan(Color.RED), 0, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); //红色高亮
- tSS.setSpan(new UnderlineSpan(), 15, 18,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); //下划线
- tSS.setSpan(new StyleSpan(android.graphics.Typeface.BOLD_ITALIC), 2, 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); //斜体
- mTextView.setText(tSS);
关键方法:
public void setSpan (Object what, int start, int end, int flags)
start是起始位置,无论中英文,都算一个。从0开始计算起。end是结束位置,所以处理的文字,包含开始位置,但不包含结束位置。
将需要的文字高亮显示:
- public void highlight(int start,int end){
- SpannableStringBuilder spannable=
- new SpannableStringBuilder(getText().toString());//用于可变字符串
- ForegroundColorSpan span=new ForegroundColorSpan(Color.RED);
- spannable.setSpan(span, start,
- end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- setText(spannable);
- }
加下划线:
- public void underline(int start,int end){
- SpannableStringBuilder spannable=
- new SpannableStringBuilder(getText().toString());
- CharacterStyle span=new UnderlineSpan();
- spannable.setSpan(span, start,
- end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- setText(spannable);
- }
组合运用:
- SpannableStringBuilder spannable=
- new SpannableStringBuilder(getText().toString());
- CharacterStyle span_1=new StyleSpan(android.graphics.Typeface.ITALIC);
- CharacterStyle span_2=new ForegroundColorSpan(Color.RED);
- spannable.setSpan(span_1, start,
- end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- spannable.setSpan(span_2, start,
- end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- setText(spannable);
案例:带有n换行符的字符串都可以用此方法显示2种颜色
- /**
- * 带有n换行符的字符串都可以用此方法显示2种颜色
- * @param text
- * @param color1
- * @param color2
- * @return
- */
- public SpannableStringBuilder highlight(String text,int color1,int color2,int fontSize){
- SpannableStringBuilder spannable=new SpannableStringBuilder(text);//用于可变字符串
- CharacterStyle span_0=null,span_1=null,span_2;
- int end=text.indexOf("n");
- if(end==-1){//如果没有换行符就使用第一种颜色显示
- span_0=new ForegroundColorSpan(color1);
- spannable.setSpan(span_0, 0,
- text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }else{
- span_0=new ForegroundColorSpan(color1);
- span_1=new ForegroundColorSpan(color2);
- spannable.setSpan(span_0, 0,
- end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- spannable.setSpan(span_1, end+1,
- text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- span_2=new AbsoluteSizeSpan(fontSize);//字体大小
- spannable.setSpan(span_2, end+1,
- text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- return spannable;
- }
以上实际都是Html.fromHtml(html)的代码实现形式。
=============================================================================
TextView: (方法与EditView类似)
如何让一个TextView中的关键字高亮显示?
- /**
- * 关键字高亮显示
- * @param target 需要高亮的关键字
- */
- public void highlight(String target){
- String temp=getText().toString();
- SpannableStringBuilder spannable = new SpannableStringBuilder(temp);
- CharacterStyle span=null;
- Pattern p = Pattern.compile(target);
- Matcher m = p.matcher(temp);
- while (m.find()) {
- span = new ForegroundColorSpan(Color.RED);//需要重复!
- //span = new ImageSpan(drawable,ImageSpan.XX);//设置现在图片
- spannable.setSpan(span, m.start(), m.end(),
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- setText(spannable);
- }