Core Animation通常对 CALayer 的所有属性(可动画的属性)做动画,在改变layer层一些属性的时候,虽然我们都没有对其进行动画,但实际上属性的改变是渐变的,而不是立马生效。这种自定应用动画称作行为。属性修改应用行为的步骤如下
- 图层首先检测它是否有委托,并且是否实现CALayerDelegate协议指定的actionForLayer:forKey方法,如果有,直接调用并返回结果。
- 2.如果没有委托,或者委托没有实现-actionForLayer:forKey方法,图层接着检查包含属性名称对于行为映射的actions字典。
- 3.如果actions字典没有包含对应的属性,那么图层接着在它的style字典接着搜索属性名。
- 4.最后,如果在style里面也找不到对应的行为,那么图层将会直接调用定义了每个属性标准行为的-defaultActionForKey方法。
经过这一番搜索会返回一个遵守CAAction协议的对象,该action将会对图层进行相应的动画。如果想改变图层的动画行为,我们可以在2、3中进行更改,我们知道对layer做颜色改变的时候是一个默认的淡入谈出动画,现在想把它换了,我们只需要进行如下操作
self.colorLayer = [CALayer layer];
self.colorLayer.frame = CGRectMake(50.f, 100.f, 50.f, 50.f);
self.colorLayer.backgroundColor = [UIColor blueColor].CGColor;
//add a custom action
CATransition *transiton = [CATransition animation];
transiton.type = kCATransitionPush;
transiton.subtype = kCATransitionFromLeft;
self.colorLayer.actions = @{@"backgroundColor":transiton};
//add it to our view
[self.view.layer addSublayer:self.colorLayer];
当背景颜色改变的时候,动画将变为推进过度的效果,建议动手实践一下
现在来看UIKit是如何禁用隐式动画的,每个UIView对它的关联图层都扮演了一个委托,并且提供了-actionForlayer:forKey的实现方法,当不存在一个动画块的实现中,UIView对所有图层行为返回nil,但是在block范围之内,它就返回一个非空值。
验证如下
NSLog(@"%@", [self.view actionForLayer:self.view.layer forKey:@"backgroundColor"]);
[UIView beginAnimations:nil context:nil];
NSLog(@"%@", [self.view actionForLayer:self.view.layer forKey:@"backgroundColor"]);
[UIView commitAnimations];
控制台分别打印nil,和一个CABasicAnimation的对象。
当属性在动画块之外发生改变, UIView 直接通过返
回 nil 来禁用隐式动画。但如果在动画块范围之内,根据动画具体类型返回相应 的属性
还有一种禁止隐式动画的方式
[CATransaction begin];
[CATransaction setDisableActions:YES];
对应的UIKit层上的方法
[UIView beginAnimations:nil context:nil];
[UIView setAnimationsEnabled:NO];
加上这个后,不管是否在快内返回的都是nil。
到这里我们现在知道该如何对UIKit进行动画了
- 关联的图层禁用了隐式动画,对这种图层做动画的唯一办法就是使 用 的动画函数(而不是依赖 ),或者继
承 ,并覆盖方法,或者直接创建一个显式动画 - 对于单独存在的图层,我们可以通过实现图层的 - actionForLayer:forKey: 委托方法,或者提供一个 actions 字典来控制隐式动画。
呈现与模型
每个图层属性的显示值都被存储在一个叫做呈现图层的独立图层当中,他可以通 过 -presentationLayer 方法来访问。这个呈现图层实际上是模型图层的复制, 但是它的属性值代表了在任何指定时刻当前外观效果
呈现树就是通过图层树中所有图层的呈现层所形成。
CAlayer的-modelaye,在呈现图层上调用 -modelaye将会返回它正在呈现所依赖的 CALayer 。通常在一个图层上调用 --modelaye会返回 self。