动画里关于 CALayer 的一些零碎知识点

重温了一下《IOS 7 Programming: Pushing the Limits》这本书,有许多零碎的知识点,记录一下,勉强算作是学习笔记吧。

CALayer

  • Part 1

动画的基本单元就是 UIView,它是非常重量级的对象,所以不能多用。但你又想让你的 UI 看起来更酷,那就需要使用 Core Animation 了。Core Animation 中最基础也最重要的部分就是CALayer

设置 CALayer 就是设置图层的 contents 属性。和 UIView 不一样,UIView 在屏幕上第一次出现是会对自身进行绘制,而 CALayer 则不会,除非你调用setNeedsDisplay 方法标记 UIView 为需要重绘的,否则 contents 属性永远不会被更新(即便它是 nil )。

CALayer 隐式为所有支持动画的属性添加动画,比如设置一个 layer 层从一个点到另外一个点时,它不是直接跳过去的,而是会有一个渐进的过度效果。看一下LayerAnimation 的代码可能会好一点,或者自己动手试一下。可以通过设置 [CATransation setDisableAction: YES]; 来禁用动作阻止此动画。

tips: 以下 API 可以设置一个 view 过渡到另外一个 view 时的效果,挺好看的。

[UIView transitionFromView:self.view toView:anotherView duration:1 options:UIViewAnimationOptionTransitionFlipFromRight completion:nil];
隐式动画能够完成的显式动画都能完成,常见的显式动画有 CABasicAnimation , 更高级一点的又 CAKeyframeAnimation ,后者可以利用路径或点序列实现动画,并为动画单独计时。关于这两个动画的使用和拓展可以看 这篇文章。

另外推荐两个关于动画的专题文章,特别不错:

1)动画

2)ios-Core-Animation-Advanced-Techniques(翻译)

3) Animating the Drawing of a CGPath With CAShapeLayer,效果挺好的,可以看一下。

  • Part 2
动画中的一个常见问题就是麻烦的“闪回”(jump back)问题。错误如下:
    CABasicAnimation *fade;
    fade = [CABasicAnimation animationWithKeyPath:@"opacity"];
    fade.duration = 1;
    fade.fromValue = @1.0;
    fade.toValue = @0.0;
    [circleLayer addAnimation:fade forKey:@"fade"];
这段代码会让圆圈淡出大约 1 秒钟,之后突然出现。要了解突然出现的原因,需要明了 模型层表示层的区别。
模型层是由“真正” CALayer 对象的属性定义的。前面的代码没有任何地方修改 circleLayer 本身。相反,CAAnimation 创建了 circleLayer 的副本并对其进行修改,使其变成 表示层。它们大致表示会在屏幕上显示什么内容。从技术上讲还存在一个 渲染层,真正表示屏幕上要显示的内容,不过它是 Core Animation 内部的功能,你很少会遇到它。如果想深入学习图层树,看上面提到的 ios-Core-Animation-Advanced-Techniques 部分内容,阐述得很详细。
那么前面的代码发生了什么呢? CAAnimation 修改了表示层,表示层将被绘制到屏幕上,绘制完成后,所有的更改都会丢失并由模型层决定新状态。模型层没有改变,因此会恢复一开始的状态。解决办法是设置模型层,如下设置:
    circleLayer.opacity = 0;
    CABasicAnimation *fade;
    fade = [CABasicAnimation animationWithKeyPath:@"opacity"];
    fade.duration = 1;
    fade.fromValue = @1.0;
    fade.toValue = @0.0;
    [circleLayer addAnimation:fade forKey:@"fade"];
有时它能正常工作,但有时 setOpacity: 中的隐式动画会与 animationWithKeyPath: 的显式动画冲突。最好的解决办法是在执行显式动画时关闭隐式动画:
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    circleLayer.opacity = 0;
    CABasicAnimation *fade;
    fade = [CABasicAnimation animationWithKeyPath:@"opacity"];
    fade.duration = 1;
    fade.fromValue = @1.0;
    fade.toValue = @0.0;
    [circleLayer addAnimation:fade forKey:@"fade"];
    [CATransaction commit];
- ---------------------------------------------------- voice ------------------------------------------------------------------------------------------------------
important note:有人推荐设置 removedOnCompletion 为 NO、fillMode 为 kCAFillModeBoth。这并不是好的解决办法。它本质上会让动画一直执行,这意味着模型永远不更新。如果你想要获得属性的值,得到的只是模型的值,而不是真正绘制在屏幕上的内容。如果之后试着对属性应用隐式动画,它不会正常工作,因为 CAAnimation 仍然在运行。如果你通过其他名称相同的动画进行替换来移除动画,那么调用 removeAnimationForKey: 或 removeAllAnimations 后就会获取旧值。而且这样会浪费内存。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------


你可能感兴趣的:(iOS,iOS基础)