I want to animate my UIProgressView
progression from 0 to 1 during 10 seconds.
Code:
[UIView animateWithDuration:10.0 animations:^{ [_myProgressView setProgress:1 animated:YES]; } completion:(BOOL finished)^{ if (finished) NSLog(@"animation finished); }];
Animation is working fine except that completion and NSLog
are always called instantly.
I tried animateWithDuration: withDelay:
but the delay is not respected and executed immediately.
Has anyone encountered the same problem?
Thanks for you help.
Its an old problem but I am still posting the solution here. The solution turned out to be really simple. All you need to do is:
[_myProgressView setProgress:1]; [UIView animateWithDuration:10.0 animations:^{ [_myProgressView layoutIfNeeded]; } completion:^(BOOL finished){ if (finished) NSLog(@"animation finished"); }];
Here is a good explanation for why things were working incorrectly for you: http://blog.spacemanlabs.com/2012/08/premature-completion-an-embarrassing-problem/
So you can not use setProgress:animated:
method to animate the progress view and get your desired behaviour of completion
block as well. However, just setting progress
inside the block will not animate it, since progress
is not an animatable property.
Refer to apple documentation which says its necessary for the property to be animatable: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/occ/clm/UIView/animateWithDuration:animations:
So you just update the value of progress
property outside the animate block and do the layout of the view inside the animate block.
None of these answers really worked for me. I was able to get the progress to animate, but for some reason it had a delay in the beginning (especially for longer durations).
The key for me, was to call layoutIfNeeded
inside an animation block and wait on the completion before doing the 2nd animation. This code is called from viewDidLoad
. With the following code, I was able to achieve a perfectly smooth timer animation.
// For some reason, the first layoutIfNeeded() needs to be wrapped in an animation block, even though it is supposedly a synchronous call. Otherwise, the progress just jumps right to 100% UIView.animate(withDuration: 0.0, animations: { self.progressView.layoutIfNeeded() }, completion: { finished in self.progressView.progress = 1.0 UIView.animate(withDuration: self.timerDuration, delay: 0.0, options: [.curveLinear], animations: { self.progressView.layoutIfNeeded() }, completion: { finished in print("animation completed") }) })
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With