CABasicAnimation not animating my property

后端 未结 3 931
春和景丽
春和景丽 2021-02-09 02:39

I\'ve been trying to understand what is wrong with my animation and I still haven\'t figure it out. I think it should be really straight forward, but there is probably something

3条回答
  •  梦谈多话
    2021-02-09 02:45

    So it's good that you've figured things out here, but your answer to your own question has some inaccuracies. Let me correct a few things:

    The frame property can be animated--just not with explicit animation. If you do the following to a layer other than the root layer of a view, the frame will animate just fine:

    [CATransaction begin];
    [CATransaction setAnimationDuration:2.0f];
    [animationLayer setFrame:CGRectMake(100.0f, 100.0f, 100.0f, 100.0f)];
    [CATransaction commit];
    

    Remember that setting a property on a layer will animate that property change by default. In fact you have to disable animations on a property change if you don't want it to animate. (Of course this is only true if you are animating a layer other than the root layer of a view.) You are correct in animating both position and bounds if you need to use an explicit animation.

    You can animate the frame on a UIView using implicit animation:

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:3.0f];
    [[self view] setFrame:CGRectMake(45.0f, 45.0f, 100.0f, 100.0f)];
    [UIView commitAnimations];
    

    This will animate from the view's current frame (bounds and position) to x = 45.0, y = 45.0, w = 100.0, h = 100.0.

    It seems you may also be misunderstanding the difference between an animation and a layer. You add animations to layers, but adding an animation to a layer does not automatically set the property that you're animating.

    CALayers are model objects. They contain information about the layer that eventually gets rendered to screen. You must set a layer's property if you want that property to actually have that value. If you simply animate the property, it will only be a visual representation and not actual--which is to say this is why the value snaps back to the original value of the layer because you never actually changed it.

    Which leads me to the next point. You said:

    Use "animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeForwards;" to ensure that the values are not reseted at the end of the animation

    This is not exactly right. These two values simply cause the animation to remain at it's final position visually, however, the layer's actual values have not changed. They are still the exact same values they were when you started the animation. In general (with a few exceptions) you don't want to use these two parameters because they are visual only. What you want is to actually set the layer value for the property you're animating.

    Say, for example, that you want to animate the position of your layer using an explicit animation. Here is the code you want:

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
    [animation setFromValue:[NSValue valueWithCGPoint:CGPointMake(70.0f, 70.0f)]];
    [animation setToValue:[NSValue valueWithCGPoint:CGPointMake(150.0f, 150.0f)]];
    [animation setDuration:2.0f];
    
    // Actually set the position on the *layer* that you want it to be
    // when the animation finishes.
    [animationLayer setPosition:CGPointMake(150.0f, 150.0f)];
    
    // Add the animation for the position key to ensure that you
    // override the animation for position changes with your animation.
    [animationLayer addAnimation:animation forKey:@"position"];
    

    You may also want to consider animation grouping. With an animation group, you can group several animations together and then control how they relate to each other. In your case the duration for your bounds and position animations are the same and so what you are trying to do will work fine without a group, but if you wanted to offset the start of the animations, for example you didn't want the position animation to start until a second or two into the frame animation, you could stagger them by setting the beginTime value of the position animation.

    Finally, I would be curious to know why you couldn't use the implicit animations available on UIView. I use these in the vast majority of the Core Animation code I write and can't see why this wouldn't work for your situation.

    Best regards.

提交回复
热议问题