使用CoreText实现的一个富文本显示组件

来源:互联网 发布:淘宝网男装新款 编辑:程序博客网 时间:2024/05/01 09:29

            开发移动应用,无法避开的一个问题就是富文本的展示和图文混排。之前一直使用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,那样的话,文字就会显示在图片上。但是这个方案和第一个方案在显示上有点冲突,笔者目前还没找到比较好的解决方案,尚待进一步研究。

       二、点击的捕获

       可以在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.未使用多线程。 本来想添加一个后台解析的功能,但是考虑到多线程的配合和管控问题,还是交由用户来实现,代码也不复杂,用户完全可以自行分离并添加多线程功能。毕竟笔者写的是一个展示组件,而不是一整套的解决方案。

        优点就是轻量、易用易懂。



        本文欢迎转载,转载请注明出处。

0 0
原创粉丝点击