图文混排有多种方式可以实现,下面我会用四种不同的方式来实现以下界面的效果,并且说明他们的优缺点。
NSAttributedString
NSAttributedString提供了自由并且多样式的富文本设置,图文混排的实现是通过插入NSTestAttachment来实现。
talk is cheap ,here is the code
1 | //调用 |
以下是NSAttributedString的属性
1 | // NSFontAttributeName 设置字体属性,默认值:字体:Helvetica(Neue) 字号:12 |
NSParagraphStyle的属性
1 | NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; |
TextView + UIImageview
以上的效果同样可以使用UITextView + UIImageView来实现,该方法主要利用了textview的textContainer.exclusionPaths属性
// Default value : empty array An array of UIBezierPath representing the exclusion paths inside the receiver’s bounding rect.
@property (copy, NS_NONATOMIC_IOSONLY) NSArray
按照文档的说明我们可以提供一个元素为UIBezierPath的数组,这样文字的描绘就会避开这些路径。从而实现图文混排的效果。不过这种方式最适合用于文字环绕的效果,所有的文字把图片包围住。
here is the code
1 | // 调用 |
CoreText
coreText给我的感觉就是太难用了,但是可创造性又很高,因为CoreText是属于比较底层的框架,所以基本上都是使用的C的方法,CoreText可以实现很复杂的图文混排而且渲染速度更快。
CoreText来实现图文混排实际上分为以下的几步:
获得上下文,翻转坐标系 -> 创建NSAttributeString -> 创建空白占位图片,创建代理 -> 实现代理 -> 创建CTFrameRef,CTFrameDraw绘制 -> 计算图片坐标,CGContextDrawImage绘制 -> 释放资源
CFAttributedStringRef :属性字符串,用于存储需要绘制的文字字符和字符属性
CTFramesetterRef:通过CFAttributedStringRef进行初始化,作为CTFrame对象的生产工厂,负责根据path创建对应的CTFrame
CTFrame:用于绘制文字的类,可以通过CTFrameDraw函数,直接将文字绘制到context上
CTLine:在CTFrame内部是由多个CTLine来组成的,每个CTLine代表一行
CTRun:每个CTLine又是由多个CTRun组成的,每个CTRun代表一组显示风格一致的文本
实际上CoreText是不直接支持绘制图片的,但是我们可以先在需要显示图片的地方用一个特殊的空白占位符代替,同时设置该字体的CTRunDelegate信息为要显示的图片的宽度和高度,这样绘制文字的时候就会先把图片的位置留出来,再在drawRect方法里面用CGContextDrawImage绘制图片。
Here is the code
1 | -(void)drawRect:(CGRect)rect |
YYText
YYText
YYText是大神郭曜源开发的一个强大的展示和编辑富文本的第三方工具,里面提供了丰富的与富文本开发相关的方法,具体的可以到github里面看。YYText是基于CoreText向上封装了一层,所以对开发者更加友好,如果在项目中运用到大量的富文本的地方建议可以用YYText。
here is the code
1 | YYLabel *label = [[YYLabel alloc]init]; |
总结:
总的来说,以上说的四种都各有优劣,但是他们都用了NSAttributedString来实现富文本。
如果在项目中用到富文本的地方不多,出于APP体积考虑没必要引入一个第三方, 可以考虑使用第一和第二种方案,如果是图文环绕这种,可以使用UITextView+UIImageview的方案,如果是小的表情图文混排可以使用NSAttributedString+label即可。
如果在项目中多处用到富文本的展示和编辑,建议使用YYText,因为它对于开发者更加友好,并且也是基于CoreText来渲染,不过有一点就是目前YYText已经有一年没维护了,之前他生病了,现在正在家里修养,希望他快点好起来,祝好。
突然有感
本来这篇文章到这里就应该完了,不过刚刚去看了一下YYKit的作者的博客,突然有点伤感,没想到他生病这么严重,看他的文字感觉他是一个对待生活也很细腻的人,这也说得通为什么他可以用业余的时间写出了YYKIT这么强大的工具,因为他对待技术也是很细腻。
真的很佩服这样的人,你可以感受到他的真诚,我虽然没和他聊过天,没见过他真人,不过他一定会是一个让别人感受到交流沟通起来让你没有防御的一个人。现在这个社会因为各种各样变态的人以及事,总会让人无论何时何地总会身上架着一层防御装,更可怕的是还有那种表面善内里恶的人,多可怕,如果是危害别人的人我一点都不心疼。
最后希望大家一定要注意自己的身体,祝大家都好。