YYText 源码解析 —— YYLabel (一)

作者: sim_cai | 来源:发表于2016-08-12 07:32 被阅读2493次

架构


(引用作者框架对比图片)

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] 这里调用的是 YYTextAsyncLayersetNeedsDisplay 。因为 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 属性完成熏染。

相关文章

网友评论

  • 萧城x:意思上 其实渲染 视图就是一张图片???
  • 0f815988b64f:UILabel 控件在 storyboard 中怎么实现文字的点击效果?yylabel 可以实现文字点击效果
    sim_cai:@Doze 你指的是长按选中文字的效果吗?可以参考一下http://www.jianshu.com/p/b15455d7d30d这篇博客的实现。。。本人也只是个菜鸟,对于YYLabel的源码还在学习中。。。不过这块实现有人写这方面的博客http://www.jianshu.com/p/c23017fb8570。。希望对你有帮助 :grin:

本文标题:YYText 源码解析 —— YYLabel (一)

本文链接:https://www.haomeiwen.com/subject/rnissttx.html