A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 大山哥哥 于 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的合理运用,能够让我们的文本内容更加丰富、格式更加鲜明,从而实现不同的显示风格。希望本文中给大家介绍的方案能给大家带来帮助。


源码.rar

42.81 KB, 下载次数: 51

源码

2 个回复

倒序浏览
非常给力的分享,还有源码下载!赞赞赞!
回复 使用道具 举报
多谢分享
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马