CALayer 是与常使用的视图层平行的图层,与视图层的最大的不同就是不能处理用户交互。
在CALayer层处理
-
阴影,圆角,带颜色的边框
-
3D变换
-
非矩形范围
-
透明遮罩
-
多级非线性动画
当满足以下条件的时候,你可能更需要使用CALayer而不是UIView
-
开发同时可以在Mac OS上运行的跨平台应用
-
使用多种CALayer的子类(见第六章,“特殊的图层“),并且不想创建额外的UIView去包封装它们所有
-
做一些对性能特别挑剔的工作,比如对UIView一些可忽略不计的操作都会引起显著的不同(尽管如此,你可能会直接想使用OpenGL绘图)
利用CALayer对图片的处理
//UIImage的CGImage属性返回的是CGImageRef 一个指向CGImage结构的指针 CGImageRef并不是一个真正的Cocoa对象,而是一个Core Foundation类型 这两者在运行时转换需要是使用bridge关键字去桥接(只有在ARC下)
//CALayer的contents属性赋值类型为CGImageRef
UIImage *snowImg = [UIImage imageNamed:@"snow"];
self.layerView.layer.contents = (__bridge id)snowImg.CGImage;
//这里出现的图片实际大小跟视图大小不符合的时候 使用UIImageView的时候可以调contentMode
//使用CALayer的时候对应的属性为contentsGravity
/*
CA_EXTERN NSString * const kCAGravityCenter
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAGravityTop
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAGravityBottom
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAGravityLeft
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAGravityRight
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAGravityTopLeft
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAGravityTopRight
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAGravityBottomLeft
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAGravityBottomRight
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAGravityResize
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAGravityResizeAspect
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAGravityResizeAspectFill
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
*/
/*
kCAGravityResizeAspect(上下边界会有一点间隙) kCAGravityResizeAspectFill(完全填充)
*/
self.layerView.layer.contentsGravity = kCAGravityResizeAspect;//等比例拉伸
/*
contentScale 目的就是让图片支持高分辨率 设置为1.0的时候就是每个点以1个像素绘制图片 2.0就是以每个点2个像素绘制图片(Retina屏显示)
*/
//手写代码设置寄宿图的时候,一定要手动的设置图层的contentScale属性
self.layerView.layer.contentsScale = [UIScreen mainScreen].scale;
/* 内容超出边界处理
* 1.UIView 对应的属性有clipsToBounds来设置是否显示超出边界的内容
* 2.CALayer对应的属性是masksToBounds 设置为YES时 只显示边界里面的内容
*/
//contentsRect 设置显示的区域 利用了单位坐标的思想 坐标值在(0,1)之间 单位坐标是一种相对值
[self addSpriteImage:snowImg withContentRect:CGRectMake(0,0,0.5,1) toLayer:_leftView.layer];
[self addSpriteImage:snowImg withContentRect:CGRectMake(0.5, 0, 0.5, 1) toLayer:_rightView.layer];
//拼合软件及图片的使用
#pragma mark - contentsCenter
//contentsCenter
/*
contentsCenter其实是一个CGRect,它定义了一个固定的边框和一个在图层上可拉伸的区域。 改变contentsCenter的值并不会影响到寄宿图的显示,除非这个图层的大小改变了,你才看得到效果
和UIImageView 的resizableImageWithCapInsets:方法作用类似
如果使用IB的时候 在属性那栏里面设置Strething里面设置
*/
#pragma mark - 自定义绘图
/*
当需要被重绘时,CALayer会请求它的代理给他一个寄宿图来显示。它通过调用下面这个方法做到的:
- (void)displayLayer:(CALayerCALayer *)layer;
趁着这个机会,如果代理想直接设置contents属性的话,它就可以这么做,不然没有别的方法可以调用了。如果代理不实现-displayLayer:方法,CALayer就会转而尝试调用下面这个方法:
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx;
在调用这个方法之前,CALayer创建了一个合适尺寸的空寄宿图(尺寸由bounds和contentsScale决定)和一个Core Graphics的绘制上下文环境,为绘制寄宿图做准备,他作为ctx参数传入。
在使用寄宿图层的时候直接调用 -(void)drawRect:
*/
}
//通过单位坐标获取区域图片
- (void)addSpriteImage:(UIImage *)image withContentRect:(CGRect)rect toLayer:(CALayer *)layer {
layer.contents = (__bridge id)image.CGImage;
layer.contentsRect = rect;
//设置填充模式
layer.contentsGravity = kCAGravityResizeAspect;
}