全国咨询/投诉热线:400-618-4000

Android培训之SpannableString的使用

更新时间:2016年07月22日17时22分 来源:Android培训学院 浏览次数:

社交软件里的SpannableString的使用
实现类似微博的信息流展示
 
简介:社交软件里常见的emoji表情、@联系人等功能,可以在一个TextView里处理图片显示和文字点击等复杂的行为,通过此文档可以掌握该功能的实现方法。
 

1.基本知识

  1. SpannableString(复合字符串)类
该类的对象可被设置为TextView的正文,在显示原有文本的基础上,增加多种富文本特性。

  1. CharacterStyle(字符格式)的子类
在上面的setSpan方法可以看到需要一个object作为参数,该参数即为CharacterStyle的子类,有文本的前景颜色、点击、背景色、图片、下划线等格式可供使用。

2.可点击文本,如 #话题#、@联系人 的处理

  1.  先上代码
下面的代码使得字符串里的“只是”两个字符可被点击,点击时会弹出Toast提示。
 
 

 
下面分析代码里的几个参数

  1. str是用于显示的原始字符串
  2. 参数1,ClickableSpan对象
声明被修饰的字符串可以被点击。被点击时会回调onClick方法,要跳转界面还是要弹个Toast,根据业务需求变化。
  1. 参数2,start
该值表示要设置为clickspan的字符串起始位置,最小值为0.
  1. 参数3,end
该值表示要设置为clickspan的字符串终止位置,最大值为文本的length.
  1. 参数4,flags
该值用于说明,当被选中文字前后新增内容,新的字符是否受span影响。从使用来看,只在使用EditText的时候才会产生影响。信息流展示只要使用SPAN_EXCLUSIVE_EXCLUSIVE 即可。

  1. 参数5,MovementMethod对象
用于分析TextView使用的所有span,在TextView发生touch事件的时候会先交由movementMethod对象判断是否有CLickableSpan需要被处理。此参数必须设置,否则ClickableSpan的onClick方法不会被回调。
  1. 匹配#话题#或@联系人,并提供点击响应。
    1. 使用正则表达式确定start和end位置
从之前的代码可以看到,设置文字点击监听的代码是固定不变的,比较费脑的是怎么确定start和end的位置。#话题#和@联系人都是固定格式的字符串,查找固定格式的字符串应使用正则表达式来处理。上代码:
 
 

  1. 参数1,,正则表达式的查询规则
本文不做讲解,有需要请自行搜索“正则表达式”。
  1. 参数2,参数3,Pattern和Matcher
都是JDK里用于处理正则表达式的类,使用方法是固定的,可以参见代码注释。
  1. TopicClickableSpan
继承自ClickableSpan,由于ClickableSpan的onClick方法参数为View,无法区分出被点击的span,需要在构造方法里传递话题字符串以供区分不同的话题。

  1. @联系人的点击处理
更换正则表达式和自定义的ClickableSpan即可。

3.emoji表情的显示处理

  1. ImageSpan
可以将文字替换为图片显示,接收的图片可以是资源id也可以是Bitmap。
  1. Emoji表情
从服务器传过来的只是字符串,但是应该具备类似[/吓死]或者/xs这样的特殊格式,客户端通过正则表达式确定表情字符串的start和end位置,将文字转换为图片并显示到文本框。
 
 
 

  1. EmojiList类
根据匹配到的表情名称查找出来的对应图片id。用于封装所有的表情资源

4.将超链接转换为图片,并提供点击处理

通过正则表达式匹配到URL的start和end位置,并且同时设置ImageSpan和ClickableSpan到该段字符上,使得该段字符串同时具备两种特性
 
 
 


5.ClickSpan和ListView的item点击事件冲突解决


5.1存在的问题
当包含ClickableSpan的TextView作为ListView的item存在时,由于点击事件的处理冲突,会导致列表的点击事件无法响应。目前网络上的解决方案只能:“ClickableSpan响应 + item单击/长按”响应,本文可以则可以“ClickableSpan 响应+ item单击 + item长按 ”响应,并且不存在滑动时会长按响应的问题。
5.2处理方法分析
5.21处理焦点方法
TextView.setMovementMethod()方法会导致TextView的点击判断被修改,使得onTouchEvent方法始终返回为true,导致ListView无法获取touch事件,所以需要在setMovementMethod后将焦点等标志位设为false
5.22自定义MovementMethodLinkMovementMethod的onTouchEvent方法里最终会调用到Touch.onTouchEvent,该方法将down事件返回为true(见下图),使得TextView始终拦截Touch事件,导致ListView的item点击无法响应。所以需要自定义LinkMovementMethod
来修改down事件的返回值,同时在TextView的onTouchEvent里根据自定义的标志位来决定是否拦截touch事件。

  1. 自定义TextView
  1. 自定义LinkMovementMethod
  1. 使用方法
使用自定义的MyTextView,Textview.setMovementMethod()改为使用TextView. setLocalLinkMovementMethod(LocalLinkMovementMethod.getInstance());
当前的解决方案保证了只在有ClickableSpan被点击时TextView才拦截touch事件,也就使得ListView的点击事件可以正常响应了。
更多详情请查看帖子:
http://bbs.itheima.com/thread-276002-1-1.html
http://bbs.itheima.com/thread-276003-1-1.html
 

 本文版权归传智播客Android培训学院所有,欢迎转载,转载请注明作者出处。谢谢!
作者:传智播客Android培训学院
首发:http://www.itcast.cn/Android

javaee

python

web

ui

cloud

test

c

netmarket

pm

Linux

movies

robot

uids

北京校区

    14天免费试学

    基础班入门课程限时免费

    申请试学名额

    15天免费试学

    基础班入门课程限时免费

    申请试学名额

    15天免费试学

    基础班入门课程限时免费

    申请试学名额

    15天免费试学

    基础班入门课程限时免费

    申请试学名额

    20天免费试学

    基础班入门课程限时免费

    申请试学名额

    8天免费试学

    基础班入门课程限时免费

    申请试学名额

    20天免费试学

    基础班入门课程限时免费

    申请试学名额

    5天免费试学

    基础班入门课程限时免费

    申请试学名额

    0天免费试学

    基础班入门课程限时免费

    申请试学名额

    12天免费试学

    基础班入门课程限时免费

    申请试学名额

    5天免费试学

    基础班入门课程限时免费

    申请试学名额

    5天免费试学

    基础班入门课程限时免费

    申请试学名额

    10天免费试学

    基础班入门课程限时免费

    申请试学名额