CATransaction:图层更改但不动画

时间:2010-06-05 19:11:15

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

当用户点按一下按钮时,我正试图在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...
}

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

任何线索都会有所帮助!

3 个答案:

答案 0 :(得分:30)

默认情况下,视图根层上的动画处于禁用状态。尝试将变换应用于视图,例如[查看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];

请记住,这只会执行动画。实际上,您必须通过调用:

来设置图层的transform属性
[layerToAnimate setTransform:combinedTransform];

也是。否则它只会快速回到起始位置。

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

CALayer *root = [view layer];

CALayer *sublayer = [[root sublayers] objectAtIndex:0];

[sublayer setTransform:combinedTransform];

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

也许这是埋藏在某个地方的文档中,但我还没有碰到它。

答案 1 :(得分:3)

将layerToAnimate委托设置为rootView.layer:

viewToAnimate.layer.delegate = rootView.layer;

假设您也将视图/图层添加到根视图/图层中。无法找到这个改变的地方,隐式动画用于工作。

答案 2 :(得分:2)

事实证明,您可以通过将其delegate属性设置为nil来打开根层的图层动画。我不知道这是不错的做法。