YYText之图文混排
1.图文混排的原理?
我觉得,查看代码前,最重要的一件事是知道图文混排到底是怎么实现的。
核心思想:生成富文本时把,一张图片先用一个占位符代替。实际渲染时,图片占位符的渲染处理会更多一些。
根据这个原理,我们开始深入的学习。本文Demo基于YYKitExample。
2.YYTextAttachmentExample
我们先看YYTextAttachmentExample.m
中的代码实现。self.view
上有3个富文本,并且末尾都带了图片。我们可以看出,设置富文本的核心方法如下,深入看看其中做了什么。
+ (NSMutableAttributedString *)attachmentStringWithContent:(id)content
contentMode:(UIViewContentMode)contentMode
attachmentSize:(CGSize)attachmentSize
alignToFont:(UIFont *)font
alignment:(YYTextVerticalAlignment)alignment;
结合代码运行流程,我们分为以下几个部分:
2.1 生成NSMutableAttributedString实例
初始化时提供了一个占位符@"\uFFFC"
,用于代替图片信息。
2.2 YYTextAttachment
说到图文混排,必然会用到NSTextAttachment
,它是NSAttributedString
的类簇,设置富文本时对应的key是NSAttachmentAttributeName
。简而言之,我们给一个NSAttributedString
实例添加图片时,就是将image实例
作为以上key的value。YYText
自身实现了一个YYTextAttachment
,作者是这么介绍的:
YYTextAttachment
是NSAttributedString
的类簇,它的实例作为富文本key属性YYTextAttachmentAttributeName
的value。当富文本包含YYTextAttachment
时,它会采用文本规则展示。比如,attachment
的内容是UIImage
时,它会被绘制为CGContext
;attachment
的内容是UIView
或CALayer
时,它会被加入到text container
的view
层或layer
层上。
2.3 YYTextRunDelegate
在这之前我们先要知道,NSAttributedString
相比于NSString
多了很多attribute
的概念,比如下划线、背景色等。每个字符都有一个字符区域,渲染每个字符多种多样的attributes
都是在这个区域的基础上的。转换成代码是什么意思呢?CoreText
的为我们提供了这个体系:
NSAttributedString
初始化后会生成CTFramesetter
,CTFramesetter
根据不同的CGPath生成对应的CTFrame
,一个CTFrame
由多行CTLine
组成,一个CTLine
会包含多个CTRun
(字形绘制的最小单元)。
结合之前说的绘制的核心思想,可以这么理解:一行带有文字和图片的富文本,包含若干个CTRun
绘制单元,图片的绘制单元相对特殊一些。为什么呢?因为CoreText
并不能直接将一个图片转换为CTRun来绘制,所以它先用占位符预留空间,而真正的图片绘制是交给CoreGraphics
完成的。
问题又来了,CoreGraphics
是如何拿到这些绘图信息(descent、ascent、width等)呢?到这终于引出了CTRunDelegate
。我们为富文本的kCTRunDelegateAttributeName
属性赋值一个CTRunDelegate
实例,CoreText
可以根据它拿到它内部的属性,如descent、ascent、width等。
2.4 小结
通过以上3个步骤,一个富文本就生成了。其中涉及到了CoreText
的许多类,尤其是NSTextAttachment
和CTRunDelegate
。还有,富文本的文本结构。详细内容,推荐《Text Programming Guide for iOS》