0%

CoreAnimation编程指南翻译(七):修改图层的默认行为

Core Animation使用操作对象实现图层的隐式动画. 操作对象遵循CAAction协议, 定义了在图层上执行时的相关行为. 所有的CAAnimation对象都实现了CAAction协议, 用于在图层属性发生变化时执行动画.

操作可以实现任意的自定义行为, 动画只是其中一种. 要实现自定义操作需要先创建操作对象, 并将其关联到图层.

自定义操作对象

自定义操作对象需要遵循CAAction协议, 并实现runActionForKey:object:arguments:方法. 在该方法中, 实现要对图层执行的操作, 比如添加动画或执行其他任务.

定义操作对象时, 还必须指定操作何时被触发. 操作触发器定义了不同的key对应不同的触发点. 操作可在以下情况下被触发:

  • 图层的属性发生变化时. 可以是图层的任何属性, 包括通过KVC添加的自定义属性. 此时操作触发点的key为属性名.
  • 图层变为可见状态, 或是被添加到图层树中. 此时操作触发点的key为kCAOnOrderIn.
  • 图层从图层树中被移除. 此时操作触发点的key为kCAOnOrderOut.
  • 图层将要执行过渡动画. 此时操作触发点的key为kCATransition.

在图层上添加操作

操作只有被添加到图层上之后才能生效. 当图层上有事件发生时, 首先会调用actionForKey:方法查找与指定key相关联的操作对象. 在此查找过程中, 有几个合适的时机可以用来提供相关的操作对象.

Core Animation按照以下顺序查找操作对象:

  1. 如果图层设置了delegate, 并且delegate实现了actionForLayer:forKey:方法, 则该方法中必须执行以下操作之一:

    • 返回与指定key相关联的操作对象.
    • 返回nil表示不处理, 此时会继续查找.
    • 返回NSNull对象, 此时查找立即结束.
  2. 在图层的actions字典中查找指定的key.

  3. 在图层的style字典中查找包含指定key的actions字典(也就是说, style字典中包含一个名为action的key, 其value也是一个字典. 图层在这个字典中查找指定的key).

  4. 调用defaultActionForKey:方法.

  5. 如果Core Animation定义了隐式操作, 则执行该操作.

如果在上面的任意时机提供了操作对象, 图层会停止查找并执行返回的操作对象. 当找到操作对象后, 会调用该操作对象的runActionForKey:object:arguments:方法. 如果查找到的操作对象为CAAnimation类型, 则可以使用该方法的默认实现来执行动画. 如果是自定义操作对象, 则必须实现该方法执行自定义操作.

对应上面操作对象的查找过程, 图层上有多个属性或方法可以关联操作对象. 关联操作对象的正确时机取决于要如何修改图层:

  • 只在特定情况下执行操作, 或是给图层设置了delegate, 此时使用actionForLayer:forKey:方法.
  • 对于未设置delegate的图层, 使用图层的actions字典.
  • 为图层上的自定义属性添加操作, 使用图层的style字典.
  • 图层基本行为相关的操作, 自定义图层子类, 并重写defaultActionForKey:方法.

Listing 6-1 展示了使用delegate提供操作对象的方法实现, 示例中替换了图层的contents, 并使用了过渡动画.

Listing 6-1 使用delegate提供操作对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (id<CAAction>)actionForLayer:(CALayer *)theLayer
forKey:(NSString *)theKey {
CATransition *theAnimation=nil;

if ([theKey isEqualToString:@"contents"]) {

theAnimation = [[CATransition alloc] init];
theAnimation.duration = 1.0;
theAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
theAnimation.type = kCATransitionPush;
theAnimation.subtype = kCATransitionFromRight;
}
return theAnimation;
}

禁用操作

使用CATransaction类可以临时禁止图层执行操作. 当修改图层部分属性时, Core Animation会提供隐式动画. 如果不需要隐式动画, 可以显式创建一个事务, 并将其kCATransactionDisableActions属性设置为true. Listing 6-2 展示了在移除图层时禁用动画的代码片段.

Listing 6-2 临时禁止图层使用操作

1
2
3
4
5
6
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue
forKey:kCATransactionDisableActions];
[aLayer removeFromSuperlayer];
[CATransaction commit];

更多关于事务的信息, 请参阅使用显示事务修改动画参数.