GustavoAzOl
GustavoAzOl

Reputation: 299

How to stop/cancel a UIProgressView progress animation?

I have a UIProgressView which must be be updated while the user holds a button. For a smooth animation I opted to use UIView.animateWithDuration instead of a Timer to update the progress.

What I expect to achieve is: the progress increases while the user holds a button, reaching 100% in 30 seconds (and then stops). If the user releases the button before the time ends, the progress bar just stops in the current progress. If the user then holds the button again, the progress resets to zero and the same process stars all over again.

Problem is I can't cancel the animation once the user releases the button. I tried to use progressView.layer.removeAllAnimation() but didn't work too.

Bellow is my code:

@IBAction func holdValueChanged(_ sender: CustomButton) {        
    if sender.isPressed {
        progressView.progress = 1.0

        UIView.animate(withDuration: 30.0, delay: 0.0, options: UIViewAnimationOptions.curveLinear, animations: { 
            self.progressView.layoutIfNeeded()
            }, completion: { (finished) in
                print("Ended progress animation")
        })
    }
    else {
        // stop progress animation
        progressView.layer.removeAllAnimations()
    }
}

Upvotes: 1

Views: 3518

Answers (2)

mikezs
mikezs

Reputation: 422

Actually this is because there is no guarantee that the layer, that is being animated is progressView.layer. That's why progressView.layer.removeAllAnimations() will not work. Try this approach:

for (CALayer *layer in self.progressBar.layer.sublayers) {
    [layer removeAllAnimations];
}

Upvotes: 2

Arkku
Arkku

Reputation: 42129

Try creating a second (short) animation from the current state to the desired stop point, e.g., something like this (untested):

UIView.animate(withDuration: 0.1, delay: 0,
               options: [ .beginFromCurrentState, .allowUserInteraction ],
               animations: {
    self.progressView.progress = 1.0; // or whatever state it stopped at
}, completion:nil);

Starting a new animation should cancel any existing ones, and .beginFromCurrentState will prevent it from jumping to the end (in case you want to end at some other point). As a bonus, the visual effect of a short animation may also be nicer than just cancelling.

Upvotes: 0

Related Questions