UIView animateWithDuration和UIProgressView setProgress

时间:2014-05-22 09:55:49

标签: ios objective-c uiviewanimation uiprogressview

我希望在10秒内将UIProgressView进度从0设置为1。

代码:

[UIView animateWithDuration:10.0 animations:^{
    [_myProgressView setProgress:1 animated:YES];
} completion:(BOOL finished)^{
    if (finished) NSLog(@"animation finished);
}];

动画工作正常,但完成后总会立即调用NSLog

我尝试了animateWithDuration: withDelay:,但延迟没有得到尊重并立即执行。

有没有人遇到同样的问题?

谢谢你的帮助。

5 个答案:

答案 0 :(得分:33)

这是一个老问题,但我仍然在这里发布解决方案。解决方案结果非常简单。 您所需要做的就是:

[_myProgressView setProgress:1];
[UIView animateWithDuration:10.0 animations:^{
    [_myProgressView layoutIfNeeded];
} completion:^(BOOL finished){
    if (finished) NSLog(@"animation finished");
}];

这是一个很好的解释,为什么事情对你来说不正确: http://blog.spacemanlabs.com/2012/08/premature-completion-an-embarrassing-problem/

因此,您无法使用setProgress:animated:方法为进度视图设置动画,并获得所需的completion块行为。但是,仅在块中设置progress不会为其设置动画,因为progress不是可动画的属性。

请参阅苹果文档,其中说明了必须使该属性具有动画效果: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/occ/clm/UIView/animateWithDuration:animations

因此,您只需更新animate块之外的progress属性值,并在animate块内进行视图布局。

答案 1 :(得分:3)

简单地使用NSTimer,

[progressview setProgress:0 animated:NO];
NSTimer *t=[NSTimer scheduledTimerWithTimeInterval: 1.0f
                                         target: self
                                       selector: @selector(progressupdate)
                                       userInfo: nil
                                        repeats: YES];

以下是更新进度的功能

-(void)progressupdate{
   if(progressview.progress<1){
      [progressview setProgress:(progressview.progress+=0.2) animated:YES];
   }
   else{
      [t invalidate];
   }
} 

希望它有所帮助......

答案 2 :(得分:2)

这是一个老问题,但我有一个类似的问题,这是我的解决方案(对不起,它在Swift中)。动画结束时调用完成部分。它位于自定义UIProgressView类中。

override func setProgress(progress: Float, animated: Bool) {

    self.progress = progress
    if animated {
        let duration: NSTimeInterval = 10.0
        UIView.animateWithDuration(duration, delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: {
            self.layoutIfNeeded()
            }, completion: { (completed) in
                self.animationDuration = nil
        })
    } else {
        self.layoutIfNeeded()
    }
}

答案 3 :(得分:1)

我发现的是一组UIview动画和进度视图动画,它们运行得更好,并且可以顺利地为进度视图制作动画。如果您只使用动画和进度视图动画的组合,则会直接触发,而不考虑UIview动画计时器。

-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    timer = [NSTimer scheduledTimerWithTimeInterval: 1.0f
                                             target: self
                                           selector: @selector(updateTimer)
                                           userInfo: nil
                                            repeats: YES];
}


- (void)updateTimer
{
    if (progressView.progress >= 1.0) {
        [timer invalidate];
    }
    [UIView animateWithDuration:1 animations:^{
        float newProgress = [self.progressView progress] + 0.125;
        [self.progressView setProgress:newProgress animated:YES];
    }];
}

随意调整动画时间以更好地平滑过渡

答案 4 :(得分:1)

这些答案中没有一个对我真正有用。我能够获得动画制作的进度,但是由于某种原因,它的开始有所延迟(尤其是持续时间较长)。

对我来说,关键是在动画块内调用layoutIfNeeded并等待完成,然后再执行第二个动画。从viewDidLoad调用此代码。使用以下代码,我可以实现完美流畅的计时器动画。

    // 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")
        })
    })