【问题标题】:When exactly do implicit animations take place in iOS?隐式动画究竟何时在 iOS 中发生?
【发布时间】:2011-01-20 15:56:38
【问题描述】:

每个人和每本书都声称在 CALayer 中发生了隐式动画。然而,到目前为止,每次我想验证这一点时,我都会硬着头皮回到设定值。根本没有动画。

这是一个项目中没有其他任何事情发生的示例。我所做的只是创建一个视图,然后获取它的 CALayer 实例并做一些应该被隐式动画处理的事情。

[theLayer setValue:[NSNumber numberWithFloat:M_PI * 1.1] forKeyPath:@"transform.rotation.z"];

另一个:

CGRect currentBounds = theLayer.bounds;
currentBounds.size.width += 120.f;
[self.animatedLayer setBounds:currentBounds];

视图当然包含一些东西,所以我可以看到变化。 我看到了视觉上的变化,但这是一个艰难的瞬间。根本没有动画。

因此,要么所有这些书都是错误的,并且在撰写有关核心动画和隐式动画的内容时考虑到了旧的 Mac OS X 知识,要么我做错了什么。谁能提供一个工作示例来演示 iPhone 上的隐式动画?

【问题讨论】:

    标签: ios core-animation


    【解决方案1】:

    UIKit 禁用隐式动画。更具体地说,与 UIView 关联的 CALayer 永远不会隐式动画。您自己创建且不与 UIView 关联的 CALayers 将采用正常的隐式动画机制。

    如果您对它的工作原理感兴趣,隐式动画会在正常的 -actionForKey: 查找之后发生。如果给定属性有 CAAction,则使用它。否则,使用隐式动画。在 CALayer 与 UIView 关联的情况下,UIView 实现 -actionForLayer:forKey: 委托方法,当不在 UIView 动画块中时,它总是返回 [NSNull null] 以表示动作查找应在此处停止。这可以防止隐式动画工作。在 UIView 动画块内部,它构造了自己的动作来表示当前的 UIView 动画设置。同样,这可以防止隐式动画。

    如果您需要动画化 UIView 不会为您执行的 CALayer 属性,您可以使用显式 CAAnimation 子类(例如 CABasicAnimation)。

    【讨论】:

    • 很好的答案!我很好奇 - 你从哪里获得所有这些详细信息?我查了很多书和资料,但都没有这些细节。
    • 主要是反复试验。如果您在 UIView 子类上覆盖 -actionForLayer:forKey:,您可以注销对 super 的调用结果并将其与是否存在活动动画块相关联。如果您考虑一下,这也很有意义 - UIView 是 CALayer 的委托,如果您想禁用隐式动画,-actionForLayer:forKey: 是挂钩的合适位置。
    • 很有意义。谢谢!
    • 但是为什么官方文档里没有写这个?!它只是说“要触发隐式动画,您所要做的就是更新图层对象的属性。”
    • @MatterGoal:您引用的文档是 CoreAnimation 文档。这是正确的;在常规的CALayer 中,隐式动画起作用。这里的诀窍是属于UIViewCALayers 禁用了它们的隐式动画。但是你自己创建的任何CALayers 仍然可以得到它们。
    【解决方案2】:

    旧帖子,但下面的链接指向核心动画编程指南中的一个部分,这有助于进一步了解 Kevin Ballard 所说的内容。确实需要一个明显的说明,提到要为 UIView 的底层属性设置动画,您需要确保将层的委托设置为将采用“actionForLayer:ForKey:”方法并返回 nil 的实例。发现你也可以将delegate设置为不采用这种方法的实例,它仍然允许隐式动画,但这是一种草率且令人困惑的做法。

    Core Animation - Layer Actions - Defined Search Pattern for Action Keys

    【讨论】:

      【解决方案3】:

      请记住,UIView 主层的子层通常不会将 UIView 作为其委托。因此,除非您明确阻止它,否则它们会参与隐式动画,即使您没有提供委托以返回 nil 操作以响应 actionForLayer:forKey:。

      因此,在通用视图中获取隐式动画的一种简单方法是添加一个覆盖主要图层的子图层。

      Matt Neuberg 的《iOS 5 编程》一书(目前在 Safari Books Online 上处于测试阶段)非常清楚地解释了这个主题。

      【讨论】:

        【解决方案4】:

        凯文巴拉德的回答完全正确。我想在这里提供更多内容。

        来自official document的详细信息

        有一节叫做:iOS中修改图层的规则,你会发现

        UIView 类默认禁用图层动画,但在动画块中重新启用它们。

        除了启用 UIView 动画块中的隐式。还有另外两个解决方案:

        1. 使您需要动画的层成为视图的子层。参考[答案][2]

          [2]: Implicit property animations do not work with CAReplicatorLayer? 的隐式动画淡入不起作用。我试过了,它按预期工作。

        2. 将图层的委托分配给图层本身。 iOS 中 layer 的默认委托是它的 backing store view,它实现了 actionForLayer:(id)layer forKey:(NSString *)key 并返回 [NSNull null] 来禁用 layer 的隐式动画。

        【讨论】:

          【解决方案5】:

          您还可以将层的委托设置为您自己的对象并处理 -actionForLayer:forKey:。即使委托没有实现 -actionForLayer:forKey: ,似乎你也会获得隐式动画。

          【讨论】:

            【解决方案6】:

            其实,你可以直接返回 nil 来获取 CALay 的默认动画。

            • (id)actionForLayer:(CALayer *)layer forKey:(NSString *)event{ 返回零; }

            【讨论】:

            • /* 如果已定义,则由 * -actionForKey: 方法的默认实现调用。应该返回一个实现 * CAAction 协议的对象。如果委托未指定 * 当前事件的行为,则可能返回“nil”。返回空对象(即 * '[NSNull null]')显式强制不再进行搜索。 (即不会调用 * +defaultActionForKey: 方法。) */
            猜你喜欢
            • 2020-10-09
            • 1970-01-01
            • 2019-10-12
            • 2015-12-25
            • 1970-01-01
            • 2012-01-15
            • 1970-01-01
            • 2019-07-29
            • 2015-10-23
            相关资源
            最近更新 更多