使用CoreText实现的一个富文本显示组件
2014-07-08 22:05
555 查看
开发移动应用,无法避开的一个问题就是富文本的展示和图文混排。之前一直使用DTCoreText这个非常强大的第三方库。但是有时候可能需求不是很大,大到需要使用这个工具的地步,而且DTCoreText的体量也不小,导入比较麻烦。最近研究了下CoreText这个框架,尝试着写了一个组件。CoreText的一些基本概念就不赘述了,网上这些方面的资料比较多。以下讲讲图文混排时遇到一些问题。
1.使用CTRunDelegate来为图片预留位置,然后再把图片绘制到预留的位置上。
2.计算出图片的位置,通过frame的path来预留位置。
第一种方案比较容易操作,而且也比较精确,所以在实现类似于表情时,采用了这种方案。CTRunDelegate提供了几个接口,可以让客户端程序员来确定该CTRun中每个Glyph的Ascent、Descent和Width,所以把图片位置预留一个字符,然后把这个字符的宽和高设为图片的宽高即可。理论上这个字符可以是任意字符,但是为了不让人看到这个字符,首先想到的是一个空格,但是空格在遇到换行时会有布局的问题,所以采用的是一个非空白字符,然后设为透明色,即可达到目的。同时为了处理字符粘连问题,为所有的表情设置不同的文本色。
第二种方案不适合做表情效果,但是可以解决一些人提出的文字环绕问题就是在创建CTFrame的时候,在path中添加一个图片的位置,由于默认的fill mode是even-odd,所以只需简单的把图片的rect添加到当前view的rect上。进一步来讲,可以在图片的rect上再添加一个rect,那样的话,文字就会显示在图片上。但是这个方案和第一个方案在显示上有点冲突,笔者目前还没找到比较好的解决方案,尚待进一步研究。
获取到落点后,可以根据之前保存的frame来计算出所在的run,以及所对应的string。但是这样做有个问题。比如一个url太长,被放到两行中显示,由于所属的line不一样,所以自然无法获取到完整的url串。所以笔者采用了实现分析出哪些是可以响应点击的字符,将他们所分布的run所在的rect保存起来,这样在点击任意一处时,可以获取到整个响应字符串,同时可以为他们绘制点击背景色。同时由于这么一个数据结构的存在,可以为每个响应串添加一个附属信息,以便返回给代理,为进一步的处理提供必要的信息。
以上所说的,都在https://github.com/skk5/SSCoreText.git
这个组件完全使用UIView绘制,不使用UIButton这种控件。可以在例子中看到使用方法。
不足:
1.可能需要写的代码比较多,因为没有默认的标签,完全需要自定制。
2.在设置段落属性中,tabstop这个还没解决。如果是在iOS7.0下可以使用系统的NSParagraphStyle。
3.在文字环绕文本中,表情的环绕有点问题,尚待解决。
4.文本的解析,是笔者自己写的,可能需要优化。而且使用的标签搜索策略是懒惰策略。
5.未使用多线程。 本来想添加一个后台解析的功能,但是考虑到多线程的配合和管控问题,还是交由用户来实现,代码也不复杂,用户完全可以自行分离并添加多线程功能。毕竟笔者写的是一个展示组件,而不是一整套的解决方案。
优点就是轻量、易用易懂。
本文欢迎转载,转载请注明出处。
一、图片的显示
有两个方案:1.使用CTRunDelegate来为图片预留位置,然后再把图片绘制到预留的位置上。
2.计算出图片的位置,通过frame的path来预留位置。
第一种方案比较容易操作,而且也比较精确,所以在实现类似于表情时,采用了这种方案。CTRunDelegate提供了几个接口,可以让客户端程序员来确定该CTRun中每个Glyph的Ascent、Descent和Width,所以把图片位置预留一个字符,然后把这个字符的宽和高设为图片的宽高即可。理论上这个字符可以是任意字符,但是为了不让人看到这个字符,首先想到的是一个空格,但是空格在遇到换行时会有布局的问题,所以采用的是一个非空白字符,然后设为透明色,即可达到目的。同时为了处理字符粘连问题,为所有的表情设置不同的文本色。
第二种方案不适合做表情效果,但是可以解决一些人提出的文字环绕问题就是在创建CTFrame的时候,在path中添加一个图片的位置,由于默认的fill mode是even-odd,所以只需简单的把图片的rect添加到当前view的rect上。进一步来讲,可以在图片的rect上再添加一个rect,那样的话,文字就会显示在图片上。但是这个方案和第一个方案在显示上有点冲突,笔者目前还没找到比较好的解决方案,尚待进一步研究。
二、点击的捕获
可以在view的touch事件中获取到点击的落点,但是注意这个point的默认坐标系是在左下角,而在做CoreText的展示时,使用的坐标系是左上角,所以需要把这个落点进行一个坐标系的转换。获取到落点后,可以根据之前保存的frame来计算出所在的run,以及所对应的string。但是这样做有个问题。比如一个url太长,被放到两行中显示,由于所属的line不一样,所以自然无法获取到完整的url串。所以笔者采用了实现分析出哪些是可以响应点击的字符,将他们所分布的run所在的rect保存起来,这样在点击任意一处时,可以获取到整个响应字符串,同时可以为他们绘制点击背景色。同时由于这么一个数据结构的存在,可以为每个响应串添加一个附属信息,以便返回给代理,为进一步的处理提供必要的信息。
以上所说的,都在https://github.com/skk5/SSCoreText.git
这个组件完全使用UIView绘制,不使用UIButton这种控件。可以在例子中看到使用方法。
不足:
1.可能需要写的代码比较多,因为没有默认的标签,完全需要自定制。
2.在设置段落属性中,tabstop这个还没解决。如果是在iOS7.0下可以使用系统的NSParagraphStyle。
3.在文字环绕文本中,表情的环绕有点问题,尚待解决。
4.文本的解析,是笔者自己写的,可能需要优化。而且使用的标签搜索策略是懒惰策略。
5.未使用多线程。 本来想添加一个后台解析的功能,但是考虑到多线程的配合和管控问题,还是交由用户来实现,代码也不复杂,用户完全可以自行分离并添加多线程功能。毕竟笔者写的是一个展示组件,而不是一整套的解决方案。
优点就是轻量、易用易懂。
本文欢迎转载,转载请注明出处。
相关文章推荐
- IOS 使用CoreText实现表情文本URL等混合显示控件
- IOS 使用CoreText实现表情文本URL等混合显示控件
- IOS 使用CoreText实现表情文本URL等混合显示控件
- IOS 使用CoreText实现表情文本URL等混合显示控件
- 第一部分实现功能:使用一个TabControl和一个Memo和TDictionary类实现文本临时存储
- 使用GridView和ImageView组件实现图片显示
- 有关打印、收藏等的JS代码(打印等主要使用了一个IE组件来实现)
- 使用JS实现将GridView中的TextBox列的值博给GridView外的一个文本筐
- PHP使用gmdate实现将一个UNIX 时间格式化成GMT文本的方法
- 【Android】使用Gallery组件实现循环显示图像
- 一个图片轮换显示的实现,使用DIV+JS,支持Firefox,IE,Safiri
- 使用GridView和ImageView组件实现图片显示效果
- 一个图片轮换显示的实现,使用DIV+JS,支持Firefox,IE,Safiri
- MFC小程序003------MFC使用WebBrowser组件,在对话框中创建滚动视图,动态创建一个静态文本控件并设置鼠标单击的消息响应
- 实现Recovery模式本地化显示文本定制(recovery_l10n工具的使用)
- 使用text-overflow:ellipsis实现溢出文本省略号显示无需js
- 字符串处理是许多程序中非常重要的一部分,它们可以用于文本显示,数据表示,查找键和很多目的.在Unix下,用户可以使用正则表达式的强健功能实现这些 目的,从Java1.4起,Java核心API就引入了java.util.regex程序包,它是一种有价值的基础
- 一个页面实现修改删除列表显示,ajax动态生成table(使用ajax,springmvc,jsp)
- Delphi组件开发教程指南(6)实现一个模拟动画显示控件
- Extjs实现多个Grid使用同一个Store,但显示不同的内容