ios - 在支持层的 View 上使用核心动画

标签 ios objective-c animation

Core Animation Programming guide ,有一段关于How to Animate Layer-Backed Views , 它说:

If you want to use Core Animation classes to initiate animations, you must issue all of your Core Animation calls from inside a view-based animation block. The UIView class disables layer animations by default but reenables them inside animation blocks. So any changes you make outside of an animation block are not animated.



还有一个例子:
[UIView animateWithDuration:1.0 animations:^{
   // Change the opacity implicitly.
   myView.layer.opacity = 0.0;

   // Change the position explicitly.
   CABasicAnimation* theAnim = [CABasicAnimation animationWithKeyPath:@"position"];
   theAnim.fromValue = [NSValue valueWithCGPoint:myView.layer.position];
   theAnim.toValue = [NSValue valueWithCGPoint:myNewPosition];
   theAnim.duration = 3.0;
   [myView.layer addAnimation:theAnim forKey:@"AnimateFrame"];
}];

在我看来,它表明如果我不在基于 View 的动画 block 内部发出 Core Animation 调用,则不会有动画。

但似乎如果我直接添加核心动画调用而没有基于 View 的动画 block ,它的工作原理是一样的。

我错过了什么吗?

最佳答案

tl;博士:该文档仅涉及隐式动画。显式动画在动画 block 之外运行良好。

我对文档的解释

文档中该引用的简化版本类似于(我对其进行了解释):

UIView have disabled implicit animations except for within animation blocks. If you want to do implicit layer animations you must do them inside an animation block.



什么是隐式动画,它们是如何工作的?

隐式动画是当独立层的可动画属性发生变化时发生的情况。例如,如果您创建一个图层并更改它的位置,它将动画到新位置。默认情况下,许多图层属性都具有此行为。

它发生这样的事情:
  • 系统启动了一个事务(没有我们做任何事情)
  • 属性的值被更改
  • 该层寻找该属性的操作
  • 在某个时间点事务被提交(没有我们做任何事情)
  • 应用找到的操作

  • 注意上面没有提到动画,而是有“ Action ”这个词。此上下文中的操作指的是实现 CAAction 的对象。协议(protocol)。它最有可能是某个 CAAnimation 子类(如 CABasicAnimation、CAKeyframeAnimation 或 CATransition),但它被构建为与任何符合该协议(protocol)的东西一起使用。

    它怎么知道要采取什么“行动”?

    通过调用 actionForKey: 来查找该属性的操作。层上。这个的默认实现按以下顺序查找操作:

    此搜索按此顺序进行(引用: actionForKey: documentation )

    1. If the layer has a delegate and that delegate implements the Accessing the Layer’s Filters method, the layer calls that method. The delegate must do one of the following:
      • Return the action object for the given key.
      • Return nil if it does not handle the action.
      • Return the NSNull object if it does not handle the action and the search should be terminated.
    2. The layer looks in the layer’s actions dictionary.
    3. The layer looks in the style dictionary for an actions dictionary that contains the key.
    4. The layer calls its defaultActionForKey: method to look for any class-defined actions.
    5. The layer looks for any implicit actions defined by Core Animation.


    UIView 在做什么?

    对于支持 View 的层, View 可以启用或禁用操作 by implementing the delegate method actionForLayer:forKey .对于正常情况(在动画 block 之外), View 通过返回 [NSNull null] 禁用隐式动画。意思是:

    it does not handle the action and the search should be terminated.



    然而,在动画 block 内, View 返回一个真实的 Action 。这可以通过手动调用 actionForLayer:forKey: 轻松验证。动画 block 的内部和外部。它也可以返回 nil这将导致图层继续寻找 Action ,如果在此之前找不到任何内容,最终会以隐式 Action (如果有)结束。

    当找到一个 Action 并提交事务时,使用常规 addAnimation:forKey: 将 Action 添加到层中。机制。这可以通过创建自定义图层子类并在 -actionForKey: 中登录来轻松验证。和 -addAnimation:forKey:然后是覆盖 +layerClass 的自定义 View 子类并返回自定义图层类。您将看到独立层实例记录了常规属性更改的两种方法,但支持层不会添加动画,除非在动画 block 中。

    为什么要对隐式动画进行这么长的解释?

    现在,为什么我要对隐式动画的工作原理给出这么长的解释?嗯,这是为了表明它们使用与您自己使用的显式动画相同的方法。知道它们是如何工作的,我们就可以理解文档说:“UIView 类默认禁用图层动画,但在动画 block 内重新启用它们”的含义。

    UIView 没有禁用显式动画的原因是您自己完成了所有工作:更改属性值,然后调用 addAnimation:forKey: .

    代码中的结果:

    动画 block 之外:
    myView.backgroundColor       = [UIColor redColor];           // will not animate :(
    myLayer.backGroundColor      = [[UIColor redColor] CGColor]; // animates :)
    
    myView.layer.backGroundColor = [[UIColor redColor] CGColor]; // will not animate :(
    [myView.layer addAnimation:myAnimation forKey:@"myKey"];     // animates :)
    

    动画 block 内部:
    myView.backgroundColor       = [UIColor redColor];           // animates :)
    myLayer.backGroundColor      = [[UIColor redColor] CGColor]; // animates :)
    
    myView.layer.backGroundColor = [[UIColor redColor] CGColor]; // animates :)
    [myView.layer addAnimation:myAnimation forKey:@"myKey"];     // animates :)
    

    您可以在上面看到独立层上的显式动画和隐式动画在动画 block 的外部和内部进行动画处理,但层支持 View 的隐式动画仅在动画 block 内部进行动画处理。

    关于ios - 在支持层的 View 上使用核心动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21226665/

    相关文章:

    ios - 适用于 iPad 的照片选择器和相机

    ios - Objective-C:后退按钮在从 AppsDelegate 呈现/推送 ViewController 后消失

    objective-c - 仅在 mac 中以编程方式截取应用程序窗口的屏幕截图

    objective-c - 如何将 NSString 中的路径转换为 ​​CFURLRef 和 FSRef*

    ios - 为新的表格 View 单元格设置暂停动画

    javascript - 是否可以将动画 svg 分配给 google Maps JavaScript API 中的标记符号?

    IOS-UICollectionView

    ios - 如何在导航 Controller 中更改从底部到顶部的过渡动画?

    ios - 从 C api 接收多维数组,如何在 Swift 中处理?

    jquery - 使用 .each() 和 setTimeout 适用于第一级动画,但不适用于第二级