【问题标题】:CATransaction: Layer Changes But Does Not AnimateCATransaction:图层更改但没有动画
【发布时间】:2011-02-28 05:29:15
【问题描述】:

当用户点击按钮时,我正在尝试为 iPad 应用程序中的部分 UI 设置动画。我的操作方法中有此代码。它的工作原理是 UI 改变了我的预期,但它并没有为这些变化设置动画。它只是立即改变。我一定错过了什么:

- (IBAction)someAction:(id)sender {
    UIViewController *aViewController = <# Get an existing UIViewController  #>;
    UIView *viewToAnimate = aViewController.view;
    CALayer *layerToAnimate = viewToAnimate.layer;

    [CATransaction begin];
    [CATransaction setAnimationDuration:1.0f];

    CATransform3D rotateTransform = CATransform3DMakeRotation(0.3, 0, 0, 1);
    CATransform3D scaleTransform = CATransform3DMakeScale(0.10, 0.10, 0.10);
    CATransform3D positionTransform = CATransform3DMakeTranslation(24, 423, 0);
    CATransform3D combinedTransform = CATransform3DConcat(rotateTransform, scaleTransform);
    combinedTransform = CATransform3DConcat(combinedTransform, positionTransform);
    layerToAnimate.transform = combinedTransform;

    [CATransaction commit];

    // rest of method...
}

我已尝试简化动画以仅更改不透明度(例如),但它仍然不会动画。不透明度会立即改变。这让我相信有些东西没有正确设置。

任何线索都会有所帮助!

【问题讨论】:

    标签: iphone objective-c cocoa ipad core-animation


    【解决方案1】:

    默认情况下禁用视图根层上的动画。尝试对视图应用变换,例如[查看 setTransform:CGTransform3D...]。如果您必须在图层级别执行此操作,请将图层添加到根图层并对其执行变换。此外,视图动画块 [UIView beginAnimations...] 仅在为视图属性设置动画时才有效——与图层属性相反。

    更新:

    这就是你的代码在显式动画下的样子(不需要 CATransaction)

    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform"];
    CATransform3D rotateTransform = CATransform3DMakeRotation(0.3, 0, 0, 1);
    CATransform3D scaleTransform = CATransform3DMakeScale(0.10, 0.10, 0.10);
    CATransform3D positionTransform = CATransform3DMakeTranslation(24, 423, 0);
    CATransform3D combinedTransform = CATransform3DConcat(rotateTransform, scaleTransform);
    combinedTransform = CATransform3DConcat(combinedTransform, positionTransform);
    [anim setFromValue:[NSValue valueWithCATransform3D:CATransform3DIdentity]];
    [anim setToValue:[NSValue valueWithCATransform3D:combinedTransform]];
    [anim setDuration:1.0f];
    
    [layerToAnimate addAnimation:anim forKey:nil];
    

    请记住,这只执行动画。你实际上必须通过调用来设置图层的转换属性:

    [layerToAnimate setTransform:combinedTransform];
    

    也是。否则它只会弹回到它的起始位置。

    在您为视图的根层设置动画的情况下,无论何时设置它们除了,层属性都会隐式动画化。在这种情况下,动画默认是关闭的,我发现当我对根动画感兴趣时,我总是需要做的是动画视图而不是图层。因此,这意味着对图层树中任何会进行属性更改的图层的调用都将被隐式动画化。例如:

    CALayer *root = [view layer];
    
    CALayer *sublayer = [[root sublayers] objectAtIndex:0];
    
    [sublayer setTransform:combinedTransform];
    

    这是我知道(知道)您可以在图层上实际使用隐式动画的唯一方法。但是,您的代码指出的是,您只需将 layer 的更改放在 UIView 动画块中即可为根图层打开图层动画。这很有趣也很方便。这是一个很有帮助的发现。

    也许这被埋在某个地方的文档中,但我还没有遇到过。

    【讨论】:

    • 这对于我的代码为什么不起作用是有道理的。我通读了核心动画编程指南和许多 CA 文档,但我从未在任何地方阅读过。您知道 Apple 是否在其文档中的任何地方声明根 CALayer 上的动画已禁用?
    • 我将动画块更改为使用 UIView 样式(而不是 CATransaction),一切都开始工作了。设置为 layer.transform 属性和 layer.opacity 的变换按预期进行动画处理。根据您的回答,这应该行不通。还是我看错了?
    • 嗯。有趣的。所以你的意思是包裹在 [UIView beginAnimations...] 和 [UIView commitAnimations] 中你动画层属性而不是视图属性并且它工作正常?伙计,就在我认为我已经确定了这些东西时,突然出现了一些其他细微差别。让我对此做一点研究。谢谢。
    • 查看我的答案的更新。您在这里发现的内容非常很有趣。
    • 从 iOS 5.1 开始......对 UIView 动画执行此操作不再有效。我猜苹果将其归类为错误并删除了它?非常烦人的是,他们有这个“神奇”功能,在文档中的任何地方都没有提到隐式动画的时间:(
    【解决方案2】:

    将您的 layerToAnimate 委托设置为您的 rootView.layer 工作:

    viewToAnimate.layer.delegate = rootView.layer;
    

    假设您也将视图/图层添加到根视图/图层。找不到此更改的位置,隐式动画用于正常工作。

    【讨论】:

      【解决方案3】:

      事实证明,您可以通过将其委托属性设置为 nil 来打开根层的层动画。我不知道这是否是个好习惯。

      【讨论】:

      • 根据CALayer class documentation:“如果图层对象是由视图创建的,视图通常会自动将自己指定为图层的代理,您不应更改这种关系。”
      • 下面,在 CALayer 的 delegate 属性的文档中:“在 iOS 中,如果图层与 UIView 对象相关联,则必须将此属性设置为拥有该图层的视图。”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-26
      • 2016-03-04
      • 1970-01-01
      • 2019-12-24
      相关资源
      最近更新 更多