CALayer CALayer3-层的属性

 

一、隐式动画属性

* 在前面几讲中已经提到,每一个UIView内部都默认关联着一个CALayer,我们可用称这个Layer为Root Layer(根层)。所有的非Root Layer,也就是手动创建的CALayer对象,都存在着隐式动画。

* 当对非Root Layer的部分属性进行相应的修改时,默认会自动产生一些动画效果,这些属性称为Animatable Properties(可动画属性)。

* 列举几个常见的Animatable Properties:

  • bounds:用于设置CALayer的宽度和高度。修改这个属性会产生缩放动画
  • backgroundColor:用于设置CALayer的背景色。修改这个属性会产生背景色的渐变动画
  • position:用于设置CALayer的位置。修改这个属性会产生平移动画

比如:假设一开始CALayer的position为(100, 100),然后在某个时刻修改为(200, 200),那么整个CALayer就会在短时间内从(100, 100)这个位置平移到(200, 200)

* 我们也可以从官方文档中查询所有的Animatable Properties

1.点击Window -> Organizer

CALayer
CALayer3-层的属性

2.在搜索框输入"animatable"即可

CALayer
CALayer3-层的属性

二、position和anchorPoint

* position和anchorPoint属性都是CGPoint类型的

* position可以用来设置CALayer在父层中的位置,它是以父层的左上角为坐标原点(0, 0)

* anchorPoint称为"定位点",它决定着CALayer身上的哪个点会在position属性所指的位置。它的x、y取值范围都是0~1,默认值为(0.5, 0.5)

1.创建一个CALayer,添加到控制器的view的layer中

CALayer
CALayer3-层的属性
 1 CALayer *myLayer = [CALayer layer];
 2 // 设置层的宽度和高度(100x100)
 3 myLayer.bounds = CGRectMake(0, 0, 100, 100);
 4 // 设置层的位置
 5 myLayer.position = CGPointMake(100, 100);
 6 // 设置层的背景颜色:红色
 7 myLayer.backgroundColor = [UIColor redColor].CGColor;
 8 
 9 // 添加myLayer到控制器的view的layer中
10 [self.view.layer addSublayer:myLayer];
CALayer
CALayer3-层的属性

第5行设置了myLayer的position为(100, 100),又因为anchorPoint默认是(0.5, 0.5),所以最后的效果是:myLayer的中点会在父层的(100, 100)位置

CALayer
CALayer3-层的属性

注意,蓝色线是我自己加上去的,方便大家理解,并不是默认的显示效果。两条蓝色线的宽度均为100。

2.若将anchorPoint改为(0, 0),myLayer的左上角会在(100, 100)位置

1 myLayer.anchorPoint = CGPointMake(0, 0);

CALayer
CALayer3-层的属性

3.若将anchorPoint改为(1, 1),myLayer的右下角会在(100, 100)位置

1 myLayer.anchorPoint = CGPointMake(1, 1);

 CALayer
CALayer3-层的属性

4.将anchorPoint改为(0, 1),myLayer的左下角会在(100, 100)位置

1 myLayer.anchorPoint = CGPointMake(0, 1);

CALayer
CALayer3-层的属性

我想,你应该已经明白anchorPoint的用途了吧,它决定着CALayer身上的哪个点会在position所指定的位置上。它的x、y取值范围都是0~1,默认值为(0.5, 0.5),因此,默认情况下,CALayer的中点会在position所指定的位置上。当anchorPoint为其他值时,以此类推。

自定义层,其实就是在层上绘图,一共有2种方法,下面详细介绍一下。

一、自定义层的方法1

方法描述:创建一个CALayer的子类,然后覆盖drawInContext:方法,使用Quartz2D API进行绘图

1.创建一个CALayer的子类

CALayer
CALayer3-层的属性

2.在.m文件中覆盖drawInContext:方法,在里面绘图

CALayer
CALayer3-层的属性
 1 @implementation MJLayer
 2 
 3 #pragma mark 绘制一个实心三角形
 4 - (void)drawInContext:(CGContextRef)ctx {
 5     // 设置为蓝色
 6     CGContextSetRGBFillColor(ctx, 0, 0, 1, 1);
 7 
 8     
 9     // 设置起点
10     CGContextMoveToPoint(ctx, 50, 0);
11     // 从(50, 0)连线到(0, 100)
12     CGContextAddLineToPoint(ctx, 0, 100);
13     // 从(0, 100)连线到(100, 100)
14     CGContextAddLineToPoint(ctx, 100, 100);
15     // 合并路径,连接起点和终点
16     CGContextClosePath(ctx);
17     
18     // 绘制路径
19     CGContextFillPath(ctx);
20 }
21 
22 @end
CALayer
CALayer3-层的属性

3.在控制器中添加图层到屏幕上

CALayer
CALayer3-层的属性
1 MJLayer *layer = [MJLayer layer];
2 // 设置层的宽高
3 layer.bounds = CGRectMake(0, 0, 100, 100);
4 // 设置层的位置
5 layer.position = CGPointMake(100, 100);
6 // 开始绘制图层
7 [layer setNeedsDisplay];
8 [self.view.layer addSublayer:layer];
CALayer
CALayer3-层的属性

注意第7行,需要调用setNeedsDisplay这个方法,才会触发drawInContext:方法的调用,然后进行绘图

CALayer
CALayer3-层的属性

二、自定义层的方法2

方法描述:设置CALayer的delegate,然后让delegate实现drawLayer:inContext:方法,当CALayer需要绘图时,会调用delegate的drawLayer:inContext:方法进行绘图。

* 这里要注意的是:不能再将某个UIView设置为CALayer的delegate,因为UIView对象已经是它内部根层的delegate,再次设置为其他层的delegate就会出问题。UIView和它内部CALayer的默认关系图:

CALayer
CALayer3-层的属性

1.创建新的层,设置delegate,然后添加到控制器的view的layer中

CALayer
CALayer3-层的属性
 1 CALayer *layer = [CALayer layer];
 2 // 设置delegate
 3 layer.delegate = self;
 4 // 设置层的宽高
 5 layer.bounds = CGRectMake(0, 0, 100, 100);
 6 // 设置层的位置
 7 layer.position = CGPointMake(100, 100);
 8 // 开始绘制图层
 9 [layer setNeedsDisplay];
10 [self.view.layer addSublayer:layer];
CALayer
CALayer3-层的属性

* 在第3行设置了CALayer的delegate,这里的self是指控制器

* 注意第9行,需要调用setNeedsDisplay这个方法,才会通知delegate进行绘图

2.让CALayer的delegate(前面设置的是控制器)实现drawLayer:inContext:方法

CALayer
CALayer3-层的属性
 1 #pragma mark 画一个矩形框
 2 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
 3     // 设置蓝色
 4     CGContextSetRGBStrokeColor(ctx, 0, 0, 1, 1);
 5     // 设置边框宽度
 6     CGContextSetLineWidth(ctx, 10);
 7     
 8     // 添加一个跟层一样大的矩形到路径中
 9     CGContextAddRect(ctx, layer.bounds);
10     
11     // 绘制路径
12     CGContextStrokePath(ctx);
13 } 
CALayer
CALayer3-层的属性

CALayer
CALayer3-层的属性

 三、其他

1.总结

无论采取哪种方法来自定义层,都必须调用CALayer的setNeedsDisplay方法才能正常绘图。

2.UIView的详细显示过程

* 当UIView需要显示时,它内部的层会准备好一个CGContextRef(图形上下文),然后调用delegate(这里就是UIView)的drawLayer:inContext:方法,并且传入已经准备好的CGContextRef对象。而UIView在drawLayer:inContext:方法中又会调用自己的drawRect:方法

* 平时在drawRect:中通过UIGraphicsGetCurrentContext()获取的就是由层传入的CGContextRef对象,在drawRect:中完成的所有绘图都会填入层的CGContextRef中,然后被拷贝至屏幕

 
 

一、隐式动画属性

* 在前面几讲中已经提到,每一个UIView内部都默认关联着一个CALayer,我们可用称这个Layer为Root Layer(根层)。所有的非Root Layer,也就是手动创建的CALayer对象,都存在着隐式动画。

* 当对非Root Layer的部分属性进行相应的修改时,默认会自动产生一些动画效果,这些属性称为Animatable Properties(可动画属性)。

* 列举几个常见的Animatable Properties:

  • bounds:用于设置CALayer的宽度和高度。修改这个属性会产生缩放动画
  • backgroundColor:用于设置CALayer的背景色。修改这个属性会产生背景色的渐变动画
  • position:用于设置CALayer的位置。修改这个属性会产生平移动画

比如:假设一开始CALayer的position为(100, 100),然后在某个时刻修改为(200, 200),那么整个CALayer就会在短时间内从(100, 100)这个位置平移到(200, 200)

* 我们也可以从官方文档中查询所有的Animatable Properties

1.点击Window -> Organizer

CALayer
CALayer3-层的属性

2.在搜索框输入"animatable"即可

CALayer
CALayer3-层的属性

二、position和anchorPoint

* position和anchorPoint属性都是CGPoint类型的

* position可以用来设置CALayer在父层中的位置,它是以父层的左上角为坐标原点(0, 0)

* anchorPoint称为"定位点",它决定着CALayer身上的哪个点会在position属性所指的位置。它的x、y取值范围都是0~1,默认值为(0.5, 0.5)

1.创建一个CALayer,添加到控制器的view的layer中

CALayer
CALayer3-层的属性
 1 CALayer *myLayer = [CALayer layer];
 2 // 设置层的宽度和高度(100x100)
 3 myLayer.bounds = CGRectMake(0, 0, 100, 100);
 4 // 设置层的位置
 5 myLayer.position = CGPointMake(100, 100);
 6 // 设置层的背景颜色:红色
 7 myLayer.backgroundColor = [UIColor redColor].CGColor;
 8 
 9 // 添加myLayer到控制器的view的layer中
10 [self.view.layer addSublayer:myLayer];
CALayer
CALayer3-层的属性

第5行设置了myLayer的position为(100, 100),又因为anchorPoint默认是(0.5, 0.5),所以最后的效果是:myLayer的中点会在父层的(100, 100)位置

CALayer
CALayer3-层的属性

注意,蓝色线是我自己加上去的,方便大家理解,并不是默认的显示效果。两条蓝色线的宽度均为100。

2.若将anchorPoint改为(0, 0),myLayer的左上角会在(100, 100)位置

1 myLayer.anchorPoint = CGPointMake(0, 0);

CALayer
CALayer3-层的属性

3.若将anchorPoint改为(1, 1),myLayer的右下角会在(100, 100)位置

1 myLayer.anchorPoint = CGPointMake(1, 1);

 CALayer
CALayer3-层的属性

4.将anchorPoint改为(0, 1),myLayer的左下角会在(100, 100)位置

1 myLayer.anchorPoint = CGPointMake(0, 1);

CALayer
CALayer3-层的属性

我想,你应该已经明白anchorPoint的用途了吧,它决定着CALayer身上的哪个点会在position所指定的位置上。它的x、y取值范围都是0~1,默认值为(0.5, 0.5),因此,默认情况下,CALayer的中点会在position所指定的位置上。当anchorPoint为其他值时,以此类推。

自定义层,其实就是在层上绘图,一共有2种方法,下面详细介绍一下。

一、自定义层的方法1

方法描述:创建一个CALayer的子类,然后覆盖drawInContext:方法,使用Quartz2D API进行绘图

1.创建一个CALayer的子类

CALayer
CALayer3-层的属性

2.在.m文件中覆盖drawInContext:方法,在里面绘图

CALayer
CALayer3-层的属性
 1 @implementation MJLayer
 2 
 3 #pragma mark 绘制一个实心三角形
 4 - (void)drawInContext:(CGContextRef)ctx {
 5     // 设置为蓝色
 6     CGContextSetRGBFillColor(ctx, 0, 0, 1, 1);
 7 
 8     
 9     // 设置起点
10     CGContextMoveToPoint(ctx, 50, 0);
11     // 从(50, 0)连线到(0, 100)
12     CGContextAddLineToPoint(ctx, 0, 100);
13     // 从(0, 100)连线到(100, 100)
14     CGContextAddLineToPoint(ctx, 100, 100);
15     // 合并路径,连接起点和终点
16     CGContextClosePath(ctx);
17     
18     // 绘制路径
19     CGContextFillPath(ctx);
20 }
21 
22 @end
CALayer
CALayer3-层的属性

3.在控制器中添加图层到屏幕上

CALayer
CALayer3-层的属性
1 MJLayer *layer = [MJLayer layer];
2 // 设置层的宽高
3 layer.bounds = CGRectMake(0, 0, 100, 100);
4 // 设置层的位置
5 layer.position = CGPointMake(100, 100);
6 // 开始绘制图层
7 [layer setNeedsDisplay];
8 [self.view.layer addSublayer:layer];
CALayer
CALayer3-层的属性

注意第7行,需要调用setNeedsDisplay这个方法,才会触发drawInContext:方法的调用,然后进行绘图

CALayer
CALayer3-层的属性

二、自定义层的方法2

方法描述:设置CALayer的delegate,然后让delegate实现drawLayer:inContext:方法,当CALayer需要绘图时,会调用delegate的drawLayer:inContext:方法进行绘图。

* 这里要注意的是:不能再将某个UIView设置为CALayer的delegate,因为UIView对象已经是它内部根层的delegate,再次设置为其他层的delegate就会出问题。UIView和它内部CALayer的默认关系图:

CALayer
CALayer3-层的属性

1.创建新的层,设置delegate,然后添加到控制器的view的layer中

CALayer
CALayer3-层的属性
 1 CALayer *layer = [CALayer layer];
 2 // 设置delegate
 3 layer.delegate = self;
 4 // 设置层的宽高
 5 layer.bounds = CGRectMake(0, 0, 100, 100);
 6 // 设置层的位置
 7 layer.position = CGPointMake(100, 100);
 8 // 开始绘制图层
 9 [layer setNeedsDisplay];
10 [self.view.layer addSublayer:layer];
CALayer
CALayer3-层的属性

* 在第3行设置了CALayer的delegate,这里的self是指控制器

* 注意第9行,需要调用setNeedsDisplay这个方法,才会通知delegate进行绘图

2.让CALayer的delegate(前面设置的是控制器)实现drawLayer:inContext:方法

CALayer
CALayer3-层的属性
 1 #pragma mark 画一个矩形框
 2 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
 3     // 设置蓝色
 4     CGContextSetRGBStrokeColor(ctx, 0, 0, 1, 1);
 5     // 设置边框宽度
 6     CGContextSetLineWidth(ctx, 10);
 7     
 8     // 添加一个跟层一样大的矩形到路径中
 9     CGContextAddRect(ctx, layer.bounds);
10     
11     // 绘制路径
12     CGContextStrokePath(ctx);
13 } 
CALayer
CALayer3-层的属性

CALayer
CALayer3-层的属性

 三、其他

1.总结

无论采取哪种方法来自定义层,都必须调用CALayer的setNeedsDisplay方法才能正常绘图。

2.UIView的详细显示过程

* 当UIView需要显示时,它内部的层会准备好一个CGContextRef(图形上下文),然后调用delegate(这里就是UIView)的drawLayer:inContext:方法,并且传入已经准备好的CGContextRef对象。而UIView在drawLayer:inContext:方法中又会调用自己的drawRect:方法

* 平时在drawRect:中通过UIGraphicsGetCurrentContext()获取的就是由层传入的CGContextRef对象,在drawRect:中完成的所有绘图都会填入层的CGContextRef中,然后被拷贝至屏幕