How to synchronously animate a UIView and a CALayer

后端 未结 2 2153
走了就别回头了
走了就别回头了 2021-02-18 13:58

To illustrate this question, I gisted a very small Xcode project on Github (two classes, 11kb download). Have a look at the gist here or use git clone git@gist.githu

2条回答
  •  情书的邮戳
    2021-02-18 14:37

    I'm assuming that you got the end position correct and that after the animation that the view and the layer are aligned. That has nothing to do with the animation, just geometry.


    When you change the property of a CALayer that isn't the layer of a view (like in your case) it will implicitly animate to its new value. To customize this animation you could use an explicit animation, like a basic animation. Changing the frame in a basic animation would look something like this.

    CABasicAnimation *myAnimation = [CABasicAnimation animationWithKeyPath:@"frame"];
    [myAnimation setToValue:[NSValue valueWithCGRect:myNewFrame]];
    [myAnimation setFromValue:[NSValue valueWithCGRect:[myLayer frame]]];
    [myAnimation setDuration:1.0];
    [myAnimation setTimingFunction:[CAMediaTimingFuntion functionWithName: kCAMediaTimingFunctionEaseOut]];
    
    [myLayer setFrame:myNewFrame];
    [myLayer addAnimation:myAnimation forKey:@"someKeyForMyAnimation"];
    

    If the timing function and the duration of both animations are the same then they should stay aligned.

    Also note that explicit animations doesn't change the value and hat you have to both add the animation and set the new value (like in the sample above)


    Yes, there are a number of ways to achieve the same effect. One example is having the view and the layer be subviews of the same subview (that in turn is a subview of the outer frame).

    Edit

    You can't easily group the UIView-animation with an explicit animation. Neither can you use an animation group (since you are applying them to different layers) but yo can use a CATransaction:

    [CATransaction begin];
    [CATransaction setAnimationDuration:1.0];
    [CATransaction setAnimationTimingFunction:[CAMediaTimingFuntion functionWithName: kCAMediaTimingFunctionEaseOut]];
    
    // Layer animation
    CABasicAnimation *myAnimation = [CABasicAnimation animationWithKeyPath:@"frame"];
    [myAnimation setToValue:[NSValue valueWithCGRect:myNewFrame]];
    [myAnimation setFromValue:[NSValue valueWithCGRect:[myLayer frame]]];
    
    [myLayer setFrame:myNewFrame];
    [myLayer addAnimation:myAnimation forKey:@"someKeyForMyAnimation"];
    
    // Outer animation
    CABasicAnimation *outerAnimation = [CABasicAnimation animationWithKeyPath:@"frame"];
    [outerAnimation setToValue:[NSValue valueWithCGRect:myNewOuterFrame]];
    [outerAnimation setFromValue:[NSValue valueWithCGRect:[outerView frame]]];
    
    [[outerView layer] setFrame:myNewOuterFrame];
    [[outerView layer] addAnimation:outerAnimation forKey:@"someKeyForMyOuterAnimation"];
    
    [CATransaction commit];
    

提交回复
热议问题