问题一:什么是CALayer(图层)?
简而言之:使UIView可以显示在屏幕上的功能属性,UIView之所以可以显示在屏幕上完全是因为UIView内部含有一个CALayer属性
•在iOS中,能看得见摸得着的东西基本上都是UIView,比如一个按钮、一个文本标签、一个文本输入框、一个图标等等,这些都是UIView
•UIView本身不具备显示的功能,之所以能显示完全是因为它内部的图层属性(具有显示功能)
•在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层
@property(nonatomic,readonly,retain) CALayer *layer;
•当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,将所有内容绘制在自己的图层上,绘图完毕后,系统将图层映射到屏幕上,于是就完成了UIView的显示
// view的完整显示过程 // 1. view.layer准备了一个Layer Graphics Context(图层类型的上下文) // 2. 调用view.layer.delegate(view)的drawLayer:inContext:,并传入刚才准备好的上下文 // 3. view的drawLayer:inContext:方法内部又会调用view的drawRect:方法 // 4. view就可以在drawRect:方法中实现绘图代码, 所有东西最终都绘制到view.layer上面 // 5. 系统再将view.layer的内容拷贝到屏幕, 于是完成了view的显示
问题二:CALayer具有哪些属性?
九大属性:
•1.内容(比如设置为图片CGImageRef)
@property(retain) id contents;
•2.位置(默认指中点,具体由anchorPoint决定)
@property CGPoint position; // 用来设置CALayer在父层中的位置 以父层的左上角为原点(0, 0)
•3.宽度和高度
@property CGRect bounds;
•4.锚点(x,y的范围都是0-1),决定了自身视图在position的坐落点
@property CGPoint anchorPoint; // 称为“定位点”、“锚点” 决定着CALayer身上的哪个点会在position属性所指的位置 以自己的左上角为原点(0, 0) 它的x、y取值范围都是0~1,默认值为(0.5, 0.5)
•5.背景颜色(CGColorRef类型)
@property CGColorRef backgroundColor;
•6.形变属性
@property CATransform3D transform;
•7.边框颜色(CGColorRef类型)
@property CGColorRef borderColor;
•8.边框宽度
@property CGFloat borderWidth;
•9.圆角半径
@property CGColorRef borderColor;
问题三:CALayer可以用来做什么呢?
•通过操作CALayer对象,可以很方便地调整UIView的一些外观属性,比如:
Ø阴影
Ø圆角大小
Ø边框宽度和颜色
Ø… …
Ø代码示例:显示效果:
- (void)testView { // 边框宽度 self.purpleView.layer.borderWidth = 10; // // 边框颜色 self.purpleView.layer.borderColor = [UIColor blueColor].CGColor; // 圆角 self.purpleView.layer.cornerRadius = 10; // self.purpleView.layer.masksToBounds = YES; // 超出主层边框范围的内容都剪掉 // 阴影颜色 self.purpleView.layer.shadowColor = [UIColor blueColor].CGColor; // 阴影偏差 self.purpleView.layer.shadowOffset = CGSizeMake(10, 10); // 阴影不透明度 self.purpleView.layer.shadowOpacity = 0.5; }
•还可以给图层添加动画,来实现一些比较炫酷的效果(见问题六)
ps:新建图层
- (void)viewDidLoad { [super viewDidLoad]; // 新建图层 // CALayer *layer = [[CALayer alloc] init]; CALayer *layer = [CALayer layer]; layer.backgroundColor = [UIColor redColor].CGColor; layer.bounds = CGRectMake(0, 0, 100, 100); layer.position = CGPointMake(200, 200); layer.anchorPoint = CGPointMake(1, 1); layer.cornerRadius = 10; layer.masksToBounds = YES; layer.contents = (id)[UIImage imageNamed:@"lufy"].CGImage; [self.view.layer addSublayer:layer]; // 新建图层 // CALayer *layer1 = [[CALayer alloc] init]; CALayer *layer1 = [CALayer layer]; layer1.backgroundColor = [UIColor redColor].CGColor; layer1.bounds = CGRectMake(0, 0, 100, 100); layer1.position = CGPointMake(200, 200); layer1.anchorPoint = CGPointMake(0, 0); layer1.cornerRadius = 10; layer1.masksToBounds = YES; layer1.contents = (id)[UIImage imageNamed:@"lufy"].CGImage; [self.view.layer addSublayer:layer1]; }
新建图层
ps:自定义图层
@implementation WHBLayer /** * 只有明显地调用setNeedsDisplay方法,才会调用drawInContext:方法进行绘制 */ - (void)drawInContext:(CGContextRef)ctx { // 红色 CGContextSetRGBFillColor(ctx, 1, 0, 0, 1); // 添加圆 CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 50, 50)); // 实心绘制 CGContextFillPath(ctx); }
WHBLayer.m
- (void)viewDidLoad { [super viewDidLoad]; WHBLayer *layer = [WHBLayer layer]; layer.bounds = CGRectMake(0, 0, 100, 100); layer.backgroundColor = [UIColor greenColor].CGColor; layer.anchorPoint = CGPointZero; [layer setNeedsDisplay]; // 绘图 会自动调用WHBLayer的drawInContext:(CGContextRef)ctf 方法 [self.view.layer addSublayer:layer]; }
ViewController.m
问题四:为什么在CALayer中我们使用CGImageRef、CGColorRef两种数据类型来对其设置,而不用UIColor、UIImage???
原因主要:考虑移植性,跨平台性
•QuartzCore框架和CoreGraphics框架是可以跨平台使用的,在iOS和Mac OS X上都能使用
ØCALayer是定义在QuartzCore框架中的
ØCGImageRef、CGColorRef两种数据类型是定义在CoreGraphics框架中的
•但是UIKit只能在iOS中使用
ØUIColor、UIImage是定义在UIKit框架中的
•为了保证可移植性,QuartzCore不能使用UIImage、UIColor,只能使用CGImageRef、CGColorRef
问题五:既然UIView和CALayer均可在屏幕上显示图像,那又如何在二者之间做选择?
•通过CALayer,就能做出跟UIImageView一样的界面效果
•既然CALayer和UIView都能实现相同的显示效果,那究竟该选择谁好呢?
Ø对比CALayer,UIView多了一个事件处理的功能。也就是说,CALayer不能处理用户的触摸事件,而UIView可以
Ø如果显示出来的东西需要跟用户进行交互的话,用UIView;如果不需要跟用户进行交互,用UIView或者CALayer都可以
Ø当然,CALayer的性能会高一些,因为它少了事件处理的功能,更加轻量级
问题六:如何利用CALayer来产生一些动画效果?什么是隐式动画?
•所有手动创建的CALayer对象,都存在着隐式动画
•什么是隐式动画?
Ø当对非Root Layer的部分属性进行修改时,默认会自动产生一些动画效果,称这些属性为Animatable Properties(可动画属性)
•列举几个常见的Animatable Properties:
// bounds:用于设置CALayer的宽度和高度。修改这个属性会产生缩放动画 // backgroundColor:用于设置CALayer的背景色。修改这个属性会产生背景色的渐变动画 // position:用于设置CALayer的位置。修改这个属性会产生平移动画
•可以通过动画事务(CATransaction)关闭默认的隐式动画效果
[CATransaction begin]; [CATransaction setDisableActions:YES]; self.myview.layer.position = CGPointMake(10, 10); [CATransaction commit];
代码示例:
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. CALayer *layer = [CALayer layer]; layer.bounds = CGRectMake(0, 0, 100, 100); layer.backgroundColor = [UIColor redColor].CGColor; layer.position = CGPointZero; layer.anchorPoint = CGPointZero; [self.view.layer addSublayer:layer]; self.layer = layer; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { self.layer.backgroundColor = [UIColor blueColor].CGColor; // [CATransaction begin]; // 开启事务 // [CATransaction setDisableActions:YES]; self.layer.position = CGPointMake(100, 100); self.layer.opacity = 0.1; // [CATransaction commit]; // 提交事务 }
隐式动画