jeeva
jeeva

Reputation:

CABasicAnimation not changing its position property after animation completes

i am applying CABasicAnimation for position property of a layer it is animating well but after animation complete its coming back to original position how to avoid that and to make image to stay in animated position only?

Upvotes: 6

Views: 18396

Answers (5)

sktree
sktree

Reputation: 101

You can just set removedOnCompletion to NO if you want to preserve the final value. And don't forget to set the fillMode.

Swift 4+

animation.fillMode = .forwards;  
animation.isRemovedOnCompletion = false

Objective-C

animation.fillMode = kCAFillModeForwards;  //The receiver remains visible in its final state when the animation is completed.
animation.removedOnCompletion = NO;

Upvotes: 2

Andrew Zimmer
Andrew Zimmer

Reputation: 3191

There are a few different ways to solve this. My favorite is to set the object at the end of the animation, and use fromValue instead of toValue to create the animation. You can also set both fromValue and toValue to create this effect. ie

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.duration = 1.0;
animation.fromValue = [NSValue valueWithCGPoint:startPoint];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];

viewToAnimate.center = endPoint;
[viewToAnimate.layer addAnimation:animation forKey:@"slide"];

The other way to do this is to set yourself as the delegate and implement:

-(void)animationDidStop:(id)sender finished:(BOOL)finished {
     viewToAnimate.center = endPoint;
}

Upvotes: 15

Rinku
Rinku

Reputation: 920

To set the object at the end of the animation just write the code like this

#import <QuartzCore/QuartzCore.h>

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.duration = 1.0;
animation.fromValue = [NSValue valueWithCGPoint:startPoint];
animation.timingFunction = [CAMediaTimingFunction functionWithName:easing];
animation.fillMode = kCAFillModeForwards;  // This line will stop the animation at the end position of animation
animation.autoreverses = NO;

viewToAnimate.center = endPoint;
[viewToAnimate.layer addAnimation:animation forKey:@"slide"];

Upvotes: 3

Chris
Chris

Reputation: 40651

If you look at the docs for addAnimation:forKey:, it says 'Typically this is implicitly invoked'. In other words, you're not supposed to call it directly. You're actually meant to do the following instead, which is even easier than setting from and to values, you simply set the values directly on the layer:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.duration = .3;

myLayer.actions = @{@"opacity": animation};
myLayer.opacity = 0;

This will fade a layer to zero opacity.

Upvotes: 0

Paul Solt
Paul Solt

Reputation: 8415

You need to set the final position. If you only use the animation fromValue and toValue it will snap back to the original starting point. The animation uses a copy of the view/layer as it "plays" and then the animation will show the original view/layer when it finishes.

If you don't explicitly set it, it will appear to snap back, even though the view/layer never really moved.

startPoint and endPoint are CGPoints and myView is the UIView that is being animated.

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
    animation.duration = .3;
    animation.fromValue = [NSValue valueWithCGPoint:startPoint];
    animation.toValue = [NSValue valueWithCGPoint:endPoint];
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    [myView.layer addAnimation:animation forKey:@"position"];   
    myView.layer.position = endPoint;   // Must set end position, otherwise it jumps back

Upvotes: 8

Related Questions