YYText 源码解析 —— YYLabel (一)
2016-08-12 本文已影响2493人
sim_cai
架构
(引用作者框架对比图片)
YYText包括控件(YYLabel,YYTextView),布局(YYTextLayout,NSAttributedString,YYTextContainer),核心(CoreText)。
源码目录组织
YYLabel
继承关系
YYLabel 直接继承 UIView,作者自己实现 Label 的渲染。+_+
state
struct {
// 是否需要更新布局
unsigned int layoutNeedUpdate : 1;
unsigned int showingHighlight : 1;
unsigned int trackingTouch : 1;
unsigned int swallowTouch : 1;
unsigned int touchMoved : 1;
unsigned int hasTapAction : 1;
unsigned int hasLongPressAction : 1;
// 内容是否支持逐渐消失
unsigned int contentsNeedFade : 1;
} _state;
如何熏染出 Text
YYLabel 的熏染是通过 YYTextAsyncLayerDelegate
完成。 YYTextAsyncLayerDelegate
提供了 newAsyncDisplayTask
配置方法用来实现渲染。
YYTextAsyncLayer 与 YYLabel 的熏染流程
已 setText
为例,看看这个熏染的流程。
-
[self.layer setNeedsDisplay]
这里调用的是YYTextAsyncLayer
的setNeedsDisplay
。因为layerClass
方法被重写了,返回了YYTextAsyncLayer
。所以主layer所使用的类是YYTextAsyncLayer
。 -
_cancelAsyncDisplay
的实现,后续再探讨。。。记遗留问题。 - 这里
display
也被重写了,在这了执行了渲染最为关键的函数_displayAsync
。 -
YYTextAsyncLayer
提供了displaysAsynchronously
用来控制是否进行异步渲染,默认为异步熏染。
熏染
本人对 Core Graphics Framework
部分不同熟悉,个人重点对这一块代码进行学。刚才我们发现这里的渲染分为:普通渲染(ps:不知道怎么称,叫同步渲染感觉不太适合,就叫普通渲染吧)和异步渲染。这两种渲染的渲染代码处理基本是一样的,只是异步熏染增加了一些多线程的处理的考虑(比如:多线程经典的“读与写”的问题)。
所以就直接学习普通渲染部分的代码吧#^_^#
YYTextAsyncLayer 熏染学习
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.opaque, self.contentsScale);
CGContextRef context = UIGraphicsGetCurrentContext();
if (self.opaque) {
CGSize size = self.bounds.size;
size.width *= self.contentsScale;
size.height *= self.contentsScale;
CGContextSaveGState(context); {
if (!self.backgroundColor || CGColorGetAlpha(self.backgroundColor) < 1) {
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextAddRect(context, CGRectMake(0, 0, size.width, size.height));
CGContextFillPath(context);
}
if (self.backgroundColor) {
CGContextSetFillColorWithColor(context, self.backgroundColor);
CGContextAddRect(context, CGRectMake(0, 0, size.width, size.height));
CGContextFillPath(context);
}
} CGContextRestoreGState(context);
}
task.display(context, self.bounds.size, ^{return NO;});
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.contents = (__bridge id)(image.CGImage);
- 开始是调用
UIGraphicsBeginImageContextWithOptions
创建一个图片处理的上下文。 绘制结束调用UIGraphicsEndImageContext
。 - 通过
UIGraphicsGetCurrentContext
获取当前图形的上下文。 - 这里有个
opaque
属性表示是否不透明,详细属性参见。 -
CGContextSaveGState
把上下文保存到栈中。然后通过CGContextSetFillColorWithColor
设置填充颜色,CGContextAddRect
添加矩形,CGContextFillPath
填充上下文路径。 最后保存通过CGContextRestoreGState
保存最近的上下文。 - 调用
task.display
回调,这里是调用配置的渲染方法,后面再分析YYLabel
的熏染回调。YYLabel
的熏染主要通过YYTextLayout
来处理。 这么后续再做学习。 - 通过
UIGraphicsGetImageFromCurrentImageContext
当前的上下文绘制出来的图片,结束绘制。 - 最后将图片赋值给
contents
属性完成熏染。