一个图文混排问题的解决过程

需求如所示:左边的是效果图,右边的是完成后的图

               

具体需求描述:用户的回复一条就是一个cell,字数不定。当存在某种条件时,需要在文字(可能换行)的最后一个字后面添加一个能点击的删除按钮小图标,文字支持emoji表情符号。

解决过程:

1、一看到这种文字中需要穿插图片的就想到了富文本中的NSTextAttachment对象,它可以包装一个image后生成一个富文本,再给UILabel显示就能完成显示需求,但是,该对象只能包装UIImage对象,无法监听图片的点击事件,不符合要求。

2、富文本是个好的思路,NSTextAttachment差就差在无法包装UIView对象。于是找到了YYKit框架,上面有个方法能包装UIView对象生成一个富文本对象

经试验,该富文本对象无法用UILabel和UITextView显示,只能用YYLabel显示,而YYlabel继承自UIView,当富文本对象中有emoji表情时,其渲染方式/位置和UILabel有所差别,导致用NSString的boundingRectWithSize方法计算出来的YYLabel高度不对,当存在emoji表情时,经常出现...的显示不全现象,多方试验无果,放弃

3、第一种方法是能完成显示效果的,只是无法监听点击事件。于是找到了种方法,能计算UILabel最后一个字的右上角坐标,于是一个想法产生了:在这个位置添加一个看不见的按钮监听事件。计算位置方法如下

sz是计算文本不换行状态下单行的尺寸,linesSz是计算文本在换行状态下的尺寸。

通过在算出位置添加一个较大的看不见的按钮监听点击事件,大部分情况是可行的。但是,此方法有时候算出的结果不准确,且需要考虑所添加按钮超出边界显示不全的情况,也无法达到所需版本要求。

4、没辙,准备学习万恶的CoreText。看着看着,发现了CoreText的封装版本TextKit,OC接口的,顿时顺心了。TextKit主要就三个类: NSTextStorage用来保存需要显示的文本及相关属性, NSLayoutManager用来决定文本显示的格式, NSTextContainer决定文本显示的范围。这个主要能解决连接高亮、下划线、文字标记、区域显示等问题,对此问题也没有帮助

5、最后,好友提示了UITextView的一个方法,selectionRectsForRange,能够得到选中字符串的CGRect,于是问题得到了解决。

这段代码的意思就是,拿到textView的最后两个字范围,在上面添加一个按钮来监听点击事件。

这段代码就是在用户发言的文字后面添加一个透明的字符串,用来参与高度计算等,注意,该占位符不能使用数字和空格,必须用字符代替空格(主要是兼容emoji表情)。

针对TextView,采用其所显示的文字计算宽高,设置textView的size需要注意:

a、计算textView文本时,计算宽度需要比textView本身的宽度减少8

b、 textView高度必须比文字高度多2 * 8 的额外高度

 github地址:https://github.com/zhangmaliang/AddDeleteButton

 

补充: 无意中发现TextView代理方法能监听文本附件的事件交互,用第一种方法就可以了

posted @ 2016-07-06 19:56  请叫我阿亮  阅读(3228)  评论(0编辑  收藏  举报