web-dev-qa-db-ja.com

UIViewanimateWithDurationおよびUIProgressViewsetProgress

UIProgressViewの進行を0から1に10秒間アニメーション化したい。

コード:

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

アニメーションは正常に機能していますが、完了とNSLogは常に即座に呼び出されます。

私は試した animateWithDuration: withDelay:しかし、遅延は尊重されず、すぐには実行されません。

誰かが同じ問題に遭遇しましたか?

助けてくれてありがとう。

18
NtskX

それは古い問題ですが、私はまだここに解決策を投稿しています。解決策は本当に簡単であることがわかりました。あなたがする必要があるのは:

[_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を設定するだけではアニメーション化されません。

プロパティをアニメート可能にするために必要であると記載されているAppleドキュメントを参照してください: https://developer.Apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/ #// Apple_ref/occ/clm/UIView/animateWithDuration:animations

したがって、animateブロックの外側のprogressプロパティの値を更新し、animateブロックの内側でビューのレイアウトを行うだけです。

39
paresh

これらの答えのどれも私にとって本当にうまくいきませんでした。アニメーションの進行状況を確認することはできましたが、何らかの理由で最初に遅延が発生しました(特に長時間)。

私にとって重要なのは、アニメーションブロック内でlayoutIfNeededを呼び出し、完了を待ってから2番目のアニメーションを実行することでした。このコードは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")
        })
    })
4
kwahn

代わりに、次のような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];
   }
} 

それが役に立てば幸い....

これは古い質問ですが、同様の問題が発生しました。これが私の解決策です(申し訳ありませんが、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()
    }
}
2

私が見つけたのは、UIviewアニメーションとプログレスビューアニメーションの両方のセットで、より適切に機能し、プログレスビューをスムーズにアニメーション化します。アニメーションとprogressviewアニメーションの組み合わせを使用するだけの場合、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];
    }];
}

アニメーション時間を自由に調整して、より適切でスムーズな遷移を実現します

2
EmilDo