UIView & CALayer

1、区别

1.UIView 是 UIKit 的(只能 iOS 使用),CALayer 是 QuartzCore 的(这是一个跨平台的框架,既可以用在iOS 中又可以用在 Mac OS X中)

2. UIView 是 CALayer 的代理(delegate)。UIView 继承 UIResponder, CALayer 继承 NSObject, UIView 比 CALayer 多了一个事件处理的功能,也就是说,CALayer 不能处理用户的触摸事件,而 UIView 可以,但CALayer实现的是图层内容管理。

3.UIView 来自 CALayer,是 CALayer 的高层实现和封装,UIView 的所有特性来源于 CALayer 支持

4.CABasicAnimation,CAAnimation,CAKeyframeAnimation等动画类都需要加到CALayer上

5、在 CALayer 中很少使用 frame 属性,因为 frame 本身不支持动画效果,通常使用 bounds 和 position 代替。

6、CALayer 中透明度使用 opacity 表示而不是 alpha;中心点使用 position 表示而不是 center。

2、绘图

当调用 UIView 的 drawRect: 方法绘制图形、图像,这种方式本质还是在图层中绘制。只是 drawRect: 方法是由 UIKit 组件进行调用,因此里面可以使用一些 UIKit 封装的方法进行绘图。

直接绘制到图层的方法由于并非 UIKit 直接调用因此只能用原生的 Core Graphics 方法绘制。

图层绘图有两种方法,不管使用哪种方法绘制完必须调用图层的 setNeedDisplay 方法(注意是图层的方法,不是 UIView 的方法,前面我们介绍过UIView也有此方法)

2.1 通过图层代理 drawLayer:inContext: 方法绘制

过代理方法进行图层绘图只要指定图层的代理,然后在代理对象中重写 -(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx 方法即可(可以通过事件参数获得绘制的图层和图形上下文,在这个方法中绘图时所有的位置都是相对于图层而言的,图形上下文指的也是当前图层的图形上下文)。

需要注意这个方法虽然是代理方法但是不用手动实现CALayerDelegate,因为 CALayer 定义中给 NSObject 做了分类扩展,所有的 NSObject 都包含这个方法。另外设置完代理后必须要调用图层的 setNeedDisplay 方法,否则绘制的内容无法显示。

2.2 通过自定义图层 drawInContext: 方法

在自定义图层中绘图时只要自己编写一个类继承于 CALayer 然后在 drawInContext: 中绘图即可。同前面在代理方法绘图一样,要显示图层中绘制的内容也要调用图层的 setNeedDisplay 方法,否则 drawInContext 方法将不会调用。 

流程:

UIView 在显示时其根图层会自动创建一个 CGContextRef(CALayer本质使用的是位图上下文),同时调用图层代理(UIView 创建图层会自动设置图层代理为其自身)的 draw: inContext: 方法并将图形上下文作为参数传递给这个方法。而在 UIView 的 draw:inContext: 方法中会调用其 drawRect: 方法,在 drawRect: 方法中使用 UIGraphicsGetCurrentContext() 方法得到的上下文正是前面创建的上下文。

3、UIXXX -> CGXXX

CALayer 是定义在 QuartzCore 框架中的,CGImageRef、CGColorRef两种数据类型是定义在 CoreGraphics 框架中的,而 UIColor 和 UIImage 是定义在 UIKit 框架中的。

其次,QuartzCore 框架和 CoreGraphics 框架是可以跨平台使用的,在 iOS 和 Mac OS X 上都能使用

但是 UIKit 只能在iOS中使用。

所以,为了保证可移植性,QuartzCore 不能使用 UIImage、UIColor,只能使用 CGImageRef、CGColorRef。

layer.backgroundColor = [UIColor colorWithRed:0 green:146/255.0 blue:1.0 alpha:1.0].CGColor;

[layer setContents: (id)image.CGImage];

补充:

注意仅仅设置圆角,对于图形而言可以正常显示,但是对于图层中绘制的图片无法正确显示,如果想要正确显示则必须设置 masksToBounds=YES,剪切子图层。

原因是:当绘制一张图片到图层上的时候会重新创建一个图层添加到当前图层,这样一来如果设置了圆角之后虽然底图层有圆角效果,但是子图层还是矩形,只有设置了masksToBounds 为 YES 让子图层按底图层剪切才能显示圆角效果。

阴影效果无法和 masksToBounds 同时使用,因为 masksToBounds 的目的就是剪切外边框, 而阴影效果刚好在外边框。(要解决这个问题不妨换个思路:使用两个大小一样的图层,下面的图层负责绘制阴影,上面的图层用来显示图片)

参考:https://blog.csdn.net/zmmzxxx/article/details/74276077

你可能感兴趣的:(UIView & CALayer)