前言:
为了保持界面UI的整洁以及将尽可能多的内容显示在有限的空间中,往往需要将长度过长的TextView进行内容截取。本控件满足了TextView可在"完整内容"与"截取内容"两种模式下进行切换的需求,且可应用在ListView/RecyclerView中并可以动态更新内容。
截图:
静态截图如下:
这里写图片描述动态效果图可点击如下链接:
流量党慎点
项目地址:
https://github.com/Carbs0126/ExpandableTextView
主要功能:
- 限制行数,行尾添加
ClickSpan
,点击可以"展开"/"收起"两种状态切换; - 可使用在
ListView
/RecyclerView
中,效率较高; - 可在任意时刻更新
ExpandableTextView
内容(布局显示之前或者显示之后); - 可自定义行数限制,默认最多显示2行;
- 可自定义行尾
ClickSpan
是否显示,颜色,文字,按下的背景颜色; - 可添加点击此view后是否在"展开"/"收起"状态间切换;
- 文字不足最大限制行数时,不截断文字,不显示末尾的"展开"/"收起"的指示标识;
- 可自定义行尾省略语与行尾"展开"/"收起"的指示标识之间的gap文字;
说明:
- 效果参考了jQuery的readmore.js,部分代码参考了ReadMoreTextView
- 与Github上star数最多的ExpandableTextView实现原理及UI完全不同。
- 暂时未添加"收缩"/"展开"时的动画效果。
优化:
- 解决末尾显示的指示标识文字与原来文字宽度不一致时的显示问题(如原始文字与行尾指示标识文字为不同语言)。如当结尾指示标识文字较宽时,可能会显示到下一行。以此优化UI体验。
- 解决末尾单词过长或者跟随标点后,换行留下的空白问题。此问题源于TextView自带的一个属性:当结尾为完整单词或者跟随标点时会连同之前的部分文字一起换行。
- 解决文字过短时,截取文字超出边界的问题。
- 解决任何时刻为
ExpandableTextView
更新文字的问题。
不具有的功能:
- 限制字符长度。此控件只限制最大行数,不限制字符长度;
- 省略标识的位置自定义。省略标识的位置暂时只能显示在行尾,不能够指定是否在"行首"/"行中"/"行尾";
- 暂时未添加"收缩"/"展开"时的动画效果。
添加依赖
compile 'cn.carbs.android:ExpandableTextView:1.0.0'
使用方法:
有两种方法设置文字:
(1)在java中更新文字
//普通视图中的更新
etv.setText(text);
//在ListView/RecyclerView中的应用,etvWidth为控件的真实宽度,state是控件所处的状态,“收缩”/“伸展”状态
etv.updateForRecyclerView(text, etvWidth, state);
(2)在xml中直接设置文字
<cn.carbs.android.expandabletextview.library.ExpandableTextView
android:id="@+id/etv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/long_poem" />
实现原理:
- 控件继承自
TextView
,TextView
中的setText(CharSequence text)
方法为final
类型,且其内部最终调用了setText(CharSequence text, BufferType type)
,因此ExpandableTextView
Override了setText(CharSequence text, BufferType type)
方法,且TextView
在通过xml布局文件设置text时,同样最终是通过setText(CharSequence text, BufferType type)
进行赋值,因此通过Override此方法达到自定义显示text的效果; - 采用android.text.Layout类来确定在一定宽度下,特定的文本所达到的行数,如果超过最大行数,则添加收缩/展开效果;
- 为文本特定位置添加ClickableSpan,以此添加点击部分文本的响应效果;自定义
ClickableSpan
和LinkMovementMethod
,达到添加点击ClickableSpan
文字背景颜色改变的效果,感谢stackoverflow的解答; - 通过
Paint.measureText(String text)
方法,找到文本截取的最优位置,使得在行尾添加了ClickableSpan后,不会出现因文字宽度不同而导致的文本换行或者文本末尾空余过大的现象;
网友评论
private static final int MAX_LINES_ON_SHRINK = 1;这个是设置可以显示最大行数的。
如果放在listview中的某一部分会拦截item的点击事件,发生冲突的话,android:descendantFocusability="blocksDescendants"
android:focusable="true"
android:focusableInTouchMode="true"三个布局文件中添加,具体位置自行调试。
之后这个Text和item都可以分别触发不同的点击事件
踩了好多坑
有问题欢迎私信