Supertecnoboff
Supertecnoboff

Reputation: 6606

CABasicAnimation stop animation on completion - iOS

I have an iOS app which is using a CABasicAnimation on repeat:

    CABasicAnimation *fadeAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
    fadeAnim.fromValue = [NSNumber numberWithFloat:1.0];
    fadeAnim.toValue = [NSNumber numberWithFloat:0.2];
    fadeAnim.duration = 1.0;
    fadeAnim.autoreverses = YES;
    fadeAnim.repeatCount = INFINITY;
    [colourbutton.titleLabel.layer addAnimation:fadeAnim forKey:@"opacity"];

I have a button which when pressed is meant to stop the animation.

-(IBAction)stopAnim {
    [colourbutton.titleLabel.layer removeAllAnimations];
}

It works fine but one thing I am noticing is that is stops the animation suddenly, it doesn't let the animation finish. So how can I get it to finish the current animation and then stop. (Or in other words how can I get it to removeAllAnimations....withAnimation?).

On a side note, do I need to include CoreAnimation framework for this to work. So far the animation is running and I havn't imported the CoreAnimation framework.

Thanks, Dan.

Upvotes: 0

Views: 2002

Answers (2)

Mundi
Mundi

Reputation: 80265

In NKorotov's answer, he uses the presentationLayer to find out where you are in the animation. That is the correct way to go.

You could go with this solution, although IMO you would also have to calculate the duration animation correctly (based on the duration of the original animation and on how far you are along the animation path currently).

If you find it "silly" to add a new animation, you could perhaps call removeAllAnimations using dispatch_after at the correct time.

Upvotes: 0

NKorotkov
NKorotkov

Reputation: 3681

Just add another animation and after that remove the first one like this:

    CABasicAnimation *endAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    endAnimation.fromValue = @(((CALayer *)colourbutton.titleLabel.layer.presentationLayer).opacity);
    endAnimation.toValue = @(1);
    endAnimation.duration = 1.0;
    [colourbutton.titleLabel.layer addAnimation:endAnimation forKey:@"end"];
    [colourbutton.titleLabel.layer removeAnimationForKey:@"opacity"];

The key here is to use the presentation layer to get the current state. Don't forget to set the actual end state of the layer, because the animation will be removed on completion.

Upvotes: 2

Related Questions