iOS 文字环绕题的一些探究

文字环绕

想要的效果 图片为一个Button 点击查看更多或者有一个点击Acnion

iOS 文字环绕题的一些探究_第1张图片
text.png

实现方式

1 CoreText来实现 缺点实现起来比较繁琐 像是再写底层代码
2 textkit 来实现方便易用

TextKit实现

TextKit需要在 UITextView 实现
有一下功能
字距调整(Kerning)
图像附件: TextView 中添加图像
连写:


iOS 文字环绕题的一些探究_第2张图片
3333.png

段字:

结构

这是 UIKit 文本系统——TextKit 的简图:

iOS 文字环绕题的一些探究_第3张图片
b.png

从上图可以看出来,要让一个文本引擎工作,需要几个参与者。我们将从外到里介绍它们:

字符串(String):NSTextStorage 保存并管理这个字符串 使用 TextKit时,NSTextStorage 就可以让文本在动态地添加字体或颜色高亮等文本属性装饰
NSTextStorage 是一个中枢,它管理所有的文本和属性信息。系统只提供了两个存取器方法存取它们,并另外提供了两个方法来分别修改文本和属性。 NSTextStorage 是从它的父类 NSAttributedString 继承了这些方法。这就很清楚了,NSTextStorage——从文本系统看来——仅仅是一个带有属性的字符串,附带一些扩展。这两者唯一的重大不同点是 NSTextStorage 包含了一个方法,可以把所有对其内容进行的修改以通知的形式发送出来。我们等一下会介绍这部分内容。

UITextView:在 TextKit 中,有两个目的:第一,它是文本系统用来绘制的视图。提供一个供其它类绘制的区域。作为视图层级机构中唯一的组件,第二个目的是处理所有的用户交互。具体来说,Text View 实现 UITextInput 的协议来处理键盘事件,它为用户提供了一种途径来设置一个插入点或选择文本。它并不对文本做任何实际上的改变,仅仅将这些改变请求转发给刚刚讨论的 Text Storage。

NSTextContainer: 定义了一个文本可以绘制的区域。

NSLayoutManager:Layout Manager 是中心组件,就是一旦textStroge有变化,通知页面布局变化,它把所有组件粘合在一起:

  1. 这个管理器监听 Text Storage 中文本或属性改变的通知,一旦接收到通知就触发布局进程。
  2. 从 Text Storage 提供的文本开始,它将所有的字符翻译为字形。
  3. 一旦字形全部生成,这个管理器向它的 Text Containers 查询文本可用以绘制的区域。
  4. 然后这些区域被行逐步填充,而行又被字形逐步填充。一旦一行填充完毕,下一行开始填充。
  5. 对于每一行,布局管理器必须考虑断行行为(放不下的单词必须移到下一行)、连字符、内联的图像附件等等。
  6. 当布局完成,文本的当前显示状态被设为无效,然后 Layout Manager 将前面几步排版好的文本设给 Text View。
    CoreText:没有直接包含在 TextKit 中,CoreText 是进行实际排版的库。对于布局管理器的每一步,CoreText 被这样或那样的方式调用。它提供了从字符到字形的翻译,用它们来填充行,以及建议断字点。
    简而言之就是

通常由NSLayoutManager从NSTextStorage中读取出文本数据,然后根据一定的排版方式,将文本排版到NSTextContainer中,再由NSTextContainer结合UITextView将最终效果显示出来。

实现代码

一个简易的文字环绕

//转化为textView内的坐标
    CGRect ovalFrame = [_textView convertRect:pathButton.bounds
                                         fromView:pathButton];
    ovalFrame.origin.x -= _textView.textContainerInset.left;
    ovalFrame.origin.y -= _textView.textContainerInset.top;
    UIBezierPath *ovalPath = [UIBezierPath bezierPathWithOvalInRect:ovalFrame];
    _textView.textContainer.exclusionPaths = @[ovalPath];//绘制路径
    _textView.textContainer.size = CGSizeMake(200, 80);//显示区域
    _textView.textContainer.lineBreakMode = NSLineBreakByTruncatingTail;//文本裁切方式 ```
实现效果 

![text.png](http://upload-images.jianshu.io/upload_images/576060-fd92f53f7cebbca9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


参考
[Objc 中国](https://objccn.io/issue-5-1/)

你可能感兴趣的:(iOS 文字环绕题的一些探究)