CALayer(一)
CALayer并不清楚具体的响应链,并不能够响应事件,即时提供了一些方法来判断是否一个触点在图层的范围之内。
一、寄宿图
CALayer类可以包含一张图片,即寄宿图(图层中包含的图)。
(1)contents属性
此属性类型被定义为id,原则上给它赋值任何值,app仍能编译成功,但事实是如果给contents赋的不是CGImage,那么得到的图层将会是空白的。之所以这个属性被定义为id类型,是因为在Mac OS系统上,这个属性对CGImage和NSImage类型的值都起作用。
给图层的寄宿图赋值时,需要通过bridge关键字转换,例如:
layer.contents = (__bridge id _Nullable)([UIImage imageNamed:@"1.jpg"].CGImage);
用此属性赋值图片,图片可能显示得不是很正常,比如拉伸,好像被压缩的样子;若是用UIImageView赋值的话,解决此问题就是设置contentMode属性;
在CALayer中与contentMode对应的属性叫做contentsGravity,是个NSString类型,可选的常量值有:
kCAGravityCenter
kCAGravityTop
kCAGravityBottom
kCAGravityLeft
kCAGravityRight
kCAGravityTopLeft
kCAGravityTopRight
kCAGravityBottomLeft
kCAGravityBottomRight
kCAGravityResize
kCAGravityResizeAspect
kCAGravityResizeAspectFill
(2)contentScale
定义了寄宿图额像素尺寸和视图比例大小,默认情况下是一个值为1.0的浮点数。但是此属性并不是总会对屏幕上的寄宿图有影响;这是因为contents由于设置了contentsGravity属性,
如果只是想单纯的放大图层的contents图片,可以使用图层的transform和affineTransform属性来达到效果。
如果contentsScale设置为1.0,将会以每个点1个像素绘制图片,如果设置为2.0,则会以每个点2个像素绘制图片,这就是我们熟知的Retina屏幕。
(3)maskToBounds
在有些情况下,图片会超出控件的边界,在UIView有一个clipsToBounds的属性可以用来决定是否显示超出边界内容,CALayer对应的属性为maskToBounds
(4)contentsRect
此属性可以在图层边框里显示寄宿图的一个子域,比contentsGravity灵活得多;contentsRect使用的是单位坐标,其值为0到1。
(5)contentsCenter
此属性为CGRect类型,它定义了一个固定的边框和一个在图层上可拉伸的区域。 改变contentsCenter的值并不会影响到寄宿图的显示,除非这个图层的大小改变了。
默认情况下,contentsCenter是{0, 0, 1, 1}。
设置此属性显示的效果和UIImage里的-resizableImageWithCapInsets: 方法效果非常类似。
二、布局
CALayer中的布局属性有frame、bounds、position;center和position都代表了相对于父图层anchorPoint(锚点)所在的位置。
(1)锚点
图层的anchorPoint通过position来控制它的frame的位置;默认坐标是{0.5, 0.5}.
(2)Hit Testing
CALayer虽然不能响应事件,但是拥有一些方法可以处理事件:
-containsPoint:如果这个点在图层frame范围内就返回YES
-hitTest:此方法接收一个CGPoint类型参数,返回的是图层本身,或者包含这个坐标点的叶子节点图层,注意当调用图层的-hitTest:方法时,测算的顺序严格依赖于图层树当中的图层顺序(和UIView处理事件类似)。
(3)自动布局
若是想要控制CALayer的布局,最简单的方法就是用CALayerDelegate如下函数:
- (void)layoutSublayersOfLayer:(CALayer *)layer;
当图层的bounds发生改变,或者图层的-setNeedsLayout方法被调用的时候,这个函数将会被执行。
参考自iOS Core Animation;