一、CALayer和UIView
CALayer与UIView类似,是一些被层级关系树管理的矩形块,和UIView的最大不同是不能处理用户的交互。
每一个UIView都有一个CALayer的属性,它的责任是创建并且管理这个图层,以确保当子视图层级关系变化的时候,他们的关联图层也同样对应在层级关系树当中有相同的操作。
iOS提供CALayer和UIView两个平行的层级关系是为了职责分离。UIView主要是对显示内容的管理而 CALayer 主要侧重显示内容的绘制。
CALayer可以做而UIView不可以做得事情:
(1)阴影,圆角,边框
(2)3D变换
(3)非矩形范围
(4)透明遮罩
(5)多级非线性动画
CALayer *redLayer = [CALayer layer];
redLayer.backgroundColor = [UIColor redColor].CGColor;
redLayer.frame = CGRectMake(0, 0, 50, 50);
[self.view.layer addSublayer:redLayer];
二、寄宿图和contents属性
1.寄宿图:即为图层中包含的图,CALayer不仅可以创建带有简单颜色的背景图层,还可以包含一张图片。
2.contents属性
CALayer可以通过一个contents属性添加图片
UIImage *image = [UIImage imageNamed:@"icon_logo"];
CALayer *layer = [CALayer layer];
layer.frame = CGRectMake(50, 50, 50, 100);
[self.view.layer addSublayer:layer];
layer.contents = (__bridge id)image.CGImage;
需要注意:core foundation 和 cocoa对象不是类型兼容的,需要通过bridged 关键字进行转换。在ARC环境下只需要layer.contents = (id)image.CGImage;
id转换就可以了
3.contentGravity
layer.contentsGravity = kCAGravityResizeAspect;
类似于UIView中的cotentMode
4.contentsScale
contentsScale 属性定义了寄宿图的像素尺寸和视图大小的比例,默认为1.0
layer.contentsScale = [UIScreen mainScreen].scale;
5.maskToBounds
maskToBounds对于超出边界的内存剪裁,和UIView的clipsToBounds一样
6.contentsRect
contentsRect 是使用了单位坐标,单位坐标指定在0到1中间,是一个相对值,默认的contentsRect是 {0,0,1,1},意味着整个寄宿图都是可见的,如果我们指定为{0,0,0.5,0.5}就只能显示左上角的四分之一的图片。
这样我们可以得到一个实用的功能,图片拼合的用法——将多张图片整合到一张大图上面,一次性载入,相比多次载入不同的图片,好处是:内存使用,载入时间,渲染性能等等。
//contentsRect 属性
- (void)createCALayerContentsRect {
CALayer *layer1 = [CALayer layer];
layer1.frame = CGRectMake(200, 100, 50, 50);
[self.view.layer addSublayer:layer1];
CALayer *layer2 = [CALayer layer];
layer2.frame = CGRectMake(300, 100, 50, 50);
[self.view.layer addSublayer:layer2];
[self addSpriteImage:[UIImage imageNamed:@"icon_logo"] withContentRet:CGRectMake(0, 0, 0.5, 0.5) layer:layer1];
[self addSpriteImage:[UIImage imageNamed:@"icon_logo"] withContentRet:CGRectMake(0.5, 0.5, 0.5, 0.5) layer:layer2];
}
- (void)addSpriteImage:(UIImage *)image withContentRet:(CGRect)rect layer:(CALayer *)layer {
layer.contents = (id)image.CGImage;
layer.contentsGravity = kCAGravityResizeAspect;
layer.contentsRect = rect;
}
7.contentsCenter
contentsCenter 与UIImage里的 - resizableImageWithCapInsets:方法类似。
三、图层几何学
1.布局
UIView有三个布局属性:frame,bounds,center,CALayer对应的叫:frame,bounds,position
Frame代表图层的外部坐标,bounds是内部坐标{0,0}是图层的左上角。position相当于anchorPoint。
当操纵视图的frame,实际上改变的是位于视图下方的CALayer的frame,对于视图或者是图层来说,frame是根据bounds,position,transform计算而来的,当对图层做变换的时候,比如旋转或者缩放,frame实际上代表了覆盖在图层旋转之后的整个轴对齐的矩形区域,frame的宽高和bounds可能不一样了。
1420016966634141.jpeg
2.锚点
默认来说,anchorpoint位于图层的中心点,但是anchorpoint可以被移动。
self.anchorPoint = CGPointMake(0.5f,0.9f);
3.坐标系
- (CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view;
- (CGPoint)convertPoint:(CGPoint)point fromView:(nullable UIView *)view;
- (CGRect)convertRect:(CGRect)rect toView:(nullable UIView *)view;
- (CGRect)convertRect:(CGRect)rect fromView:(nullable UIView *)view;
4.翻转的几何结构
geometryFlipped 设置为yes,则子图层或者子视图本来相对于左上角放置 改为 相对于左下角放置;
5.Z坐标轴
CALayer存在一个三维空间当中,除了position和anchorPoint之外,还有zPosition和anchorPointZ。
可以改变图层的显示绘图顺序
6.Hit Testing
CGRectContainsRect(<#CGRect rect1#>, <#CGRect rect2#>)表示rect1和rect2是否相交
CGRectContainsPoint(<#CGRect rect#>, <#CGPoint point#>)表示rect中是否包含point坐标
CGRectIntersectsRect(<#CGRect rect1#>, <#CGRect rect2#>)表示rect1中是否包含rect2
-hitTest:方法接受一个CGPoint类型的参数,返回图层本身,用于判断point点击了那个图层
CGPoint point = [[touches anyObject] locationInView:self.view];
CALayer *layer = [self.view.layer hitTest:point];
NSLog(@"%@",layer);
if (layer == self.redLayer) {
NSLog(@"yes");
}
网友评论