本帖最后由 大山哥哥 于 2016-10-30 23:18 编辑
通常情况下,我们使用TextView展示的都是单一的文字内容,格式也比较固定。不过有时候我们需要对TextView中的文字进行处理,例如QQ聊天的时候,“/wx”就代表了微笑的表情,在文本显示的时候就要替换成图片的形式展示。而且,有些场景下需要我们在一串文本中掺杂一个超链接、把某个词组加粗显示等等。这时候都要我们对TextView中的内容进行处理了,如果大家出现了这样的需求,推荐大家使用一个Android中的特殊的类——SpannableString。首先我们看一些这个类的继承关系,
可以看出,SpannableString是实现了CharSequence接口的,所以我们可以把这个类的对象直接设置给TextView和EditText使用。而对字符串的处理都是通过SpannableString的setSpan(Object what, int start, int end, int flags)方法调用设置的,这里接收三个参数,第一个参数为设置的Span类型,我们接下来会详细展示,第二个和第三个参数代表文本需要处理的开始和结束的位置,最后一个参数是Span的位置是否包含开始位置和结束位置本身。接下来我们直接上代码,看一看它在各个场景下的使用。
先看第一种案例,类似于QQ表情,我们要把特殊的字符串替换为表情图片来展示。这里我们先把SpannableString创建出来,构造接受的参数就是我们需要处理的字符串,创建完成之后就可以通过setSpan的方式替换文本中的内容了。这里我们通过正则表达式替换了所有的“<img>”为应用程序的默认图标,在展示结果的时候,上方的TextView我们展示未处理的文本,下方的TextView展示处理后的内容。
[AppleScript] 纯文本查看 复制代码 // 示例1,将文字中的特定字符转换为图片显示
String string1 = "把文字中的<img>替换为应用程序图标<img><img>";
// 多次更改内容需要使用SpannableString
SpannableString spannableString1 = new SpannableString(string1);
String regex = "<img>";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(string1);
while (matcher.find()) {
spannableString1.setSpan(new ImageSpan(this, R.mipmap.ic_launcher), matcher.start(),
matcher.end(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
}
tv_1.setText(string1);
tv_1_span.setText(spannableString1);
执行效果如下,可以看出,文本的“<img>”都已经替换为了图片:
如果我们把所有的表情规则都预定义好存入数据库中,就可以进行动态的规则匹配来实现QQ表情的效果了。
接下来我们看第二个案例,如果我们想把文本转成一个超链接,类似这种效果
应该如何处理呢?
同样还是使用setSpan方法,这一次传递的参数是URLSpan,这种类型的Span可以接收所有的URL的字符串来转换为超链接。上代码:
[AppleScript] 纯文本查看 复制代码 // 示例2,将文字转换为超链接,任意的URI类型都可以设置
String string2 = "点击进入黑马程序员官网";
SpannableString spannableString2 = new SpannableString(string2);
spannableString2.setSpan(new URLSpan("http://www.itheima.com"), 0, spannableString2
.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// // 打电话
// spannableString2.setSpan(new URLSpan("tel://110"), 0, spannableString2
// .length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv_2.setText(string2);
tv_2_span.setText(spannableString2);
// 带点击事件的文本需要TextView设置MovementMethod响应
tv_2_span.setMovementMethod(LinkMovementMethod.getInstance());
通过代码我们可以看出,我们不只能设置http协议的URL来打开一个网址,也可以设置Android自支持的URI格式,例如:“tel://电话号码”来拨打电话。甚至是发送email、打开地图等都是可以的,大家可以根据自己的实际业务需求指定URI。不过这里需要注意,如果想要让文字接受点击事件的处理,就必须给TextView设置MovementMethod响应,也就是代码中的tv_2_span.setMovementMethod(LinkMovementMethod.getInstance())。
如果我们的需求不仅仅满足于此,而是希望能在点击超链接的时候自己处理点击事件,这里我们还可以使用另一个Span类型,就是ClickableSpan了,我们一起来实现一下。
[AppleScript] 纯文本查看 复制代码 // 示例3,自定义超链接文字的点击事件
String string3 = "点击弹一个吐司";
SpannableString spannableString3 = new SpannableString(string3);
spannableString3.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
Toast.makeText(MainActivity.this, "我是一个吐司", Toast.LENGTH_SHORT).show();
}
}, 0, spannableString3
.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv_3.setText(string3);
tv_3_span.setText(spannableString3);
// 带点击事件的文本需要TextView设置MovementMethod响应
tv_3_span.setMovementMethod(LinkMovementMethod.getInstance());
很简单,我们在setSpan的时候设置了一个ClickableSpan,这个抽象类中包含一个onClick的抽象方法,我们可以把自己的点击处理逻辑在此实现,相信大家已经对此不陌生了。
最后,如果我们想要设置文字的样式,例如下划线、删除线、文字上下标和文字的粗体、斜体等效果,通过SpannableString我们也可以轻松实现。在AndroidSDK中包含了以上的所有Span的类型,我们可以按照需求随意使用。附上代码和效果图:
[AppleScript] 纯文本查看 复制代码 // 示例4,设置下划线、删除线、上标和下标
String string4 = "设置下划线、删除线、上标2和下标2";
SpannableString spannableString4 = new SpannableString(string4);
// 设置下划线
spannableString4.setSpan(new UnderlineSpan(), 2, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置删除线
spannableString4.setSpan(new StrikethroughSpan(), 6, 9, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置文字为上标
spannableString4.setSpan(new SuperscriptSpan(), 12, 13, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置文字为下标
spannableString4.setSpan(new SubscriptSpan(), 16, 17, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv_4.setText(string4);
tv_4_span.setText(spannableString4);
// 示例5,设置正常字体、粗体、斜体和粗斜体
String string5 = "设置正常字体、粗体、斜体和粗斜体";
SpannableString spannableString5 = new SpannableString(string5);
//设置一个字体,默认的字体可能不支持
spannableString5.setSpan(new TypefaceSpan("monospace"), 0, spannableString5.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置文字为正常字体
spannableString5.setSpan(new StyleSpan(Typeface.NORMAL), 2, 6, Spanned
.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置文字为粗体
spannableString5.setSpan(new StyleSpan(Typeface.BOLD), 7, 9, Spanned
.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置文字为斜体
spannableString5.setSpan(new StyleSpan(Typeface.ITALIC), 10, 12, Spanned
.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置文字为粗斜体
spannableString5.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 13, 16, Spanned
.SPAN_EXCLUSIVE_EXCLUSIVE);
tv_5.setText(string5);
tv_5_span.setText(spannableString5);
通过对SpannableString的合理运用,能够让我们的文本内容更加丰富、格式更加鲜明,从而实现不同的显示风格。希望本文中给大家介绍的方案能给大家带来帮助。
|