39

設定に問題がありますUIViewAnimationOptionAutoReverse。これが私のコードです。

CALayer *aniLayer = act.viewToChange.layer;
[UIView animateWithDuration:2.0 delay:1.0 options:(UIViewAnimationCurveLinear | UIViewAnimationOptionAutoreverse) animations:^{
                    viewToAnimate.frame = GCRectMake(1,1,100,100);
                    [aniLayer setValue:[NSNumber numberWithFloat:degreesToRadians(34)] forKeyPath:@"transform.rotation"];
                } completion:nil ];

問題は、アニメーションが反転した後、ビューがアニメーション ブロックで設定されたフレームに戻ることです。ビューを成長させて「成長させず」、元の位置で停止させたい。

2 つの連続したアニメーションをプログラムしないで解決する方法はありますか?

4

4 に答える 4

98

3 つのオプションがあります。

メソッドを使用する-[UIView animateWithDuration:…]と、ブロックで行った変更がanimations問題のビューにすぐに適用されます。CAAnimationただし、古い値から新しい値にアニメーション化するビューに暗黙的に適用されるものもあります。CAAnimationビューで がアクティブな場合、表示されるビューは変更されますが、ビューの実際のプロパティは変更されません。

たとえば、次のようにします。

NSLog(@"old center: %@", NSStringFromCGPoint(someView.center));
[UIView animateWithDuration:2.0 animations: ^{ someView.center = newPoint; }];
NSLog(@"new center: %@", NSStringFromCGPoint(someView.center));

「古い中心」と「新しい中心」が異なることがわかります。newcenter は newPoint の値をすぐに反映しますただし、CAAnimation暗黙的に作成された により、ビューは引き続き古い中心に表示され、スムーズに新しい中心に移動します。アニメーションが終了すると、ビューから削除され、実際のモデル値のみが表示されるように戻ります。

を渡すUIViewAnimationOptionAutoreverseと、暗黙的に作成された に影響CAAnimationしますが、値に加えている実際の変更には影響しません。つまり、上記の例で がUIViewAnimationOptionAutoreverse定義されている場合、暗黙的に作成されたCAAnimationは oldCenter から newCenter へ、またその逆にアニメーション化されます。アニメーションは削除され、設定した値に戻りますが、まだ新しい位置にあります。

前述したように、これに対処するには 3 つの方法があります。1 つ目は、アニメーションに完了ブロックを追加して、次のように反転させることです。

最初のオプション

CGPoint oldCenter = someView.center;
[UIView animateWithDuration:2.0
                 animations: ^{ someView.center = newPoint; }
                 completion: 
   ^(BOOL finished) {
       [UIView animateWithDuration:2.0
                        animations:^{ someView.center = oldCenter; }];
   }];

2 番目のオプション

2 番目のオプションは、現在行っているようにアニメーションを自動反転し、完了ブロックでビューを元の位置に戻すことです。

CGPoint oldCenter = someView.center;
[UIView animateWithDuration:2.0
                      delay:0
                    options: UIViewAnimationOptionAutoreverse
                 animations: ^{ someView.center = newPoint; }
                 completion: ^(BOOL finished) { someView.center = oldCenter; }];

ただし、これにより、アニメーションのオートリバースが完了してから完了ブロックが実行されるまでの間にちらつきが発生する可能性があるため、おそらく最適な選択ではありません。

3 番目のオプション

最後のオプションは、単純にCAAnimation直接作成することです。変更するプロパティの最終的な値を実際に変更したくない場合は、多くの場合、これの方が簡単です。

#import <QuartzCore/QuartzCore.h>

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.autoreverses = YES;
animation.repeatCount = 1; // Play it just once, and then reverse it
animation.toValue = [NSValue valueWithCGPoint:newPoint];
[someView.layer addAnimation:animation forKey:nil];

CAAnimation物事を行う方法がビューの実際の値を変更することは決してないことに注意してください。アニメーションで実際の値をマスクするだけです。ビューはまだ元の場所にあると考えています。(これは、たとえば、ビューがタッチ イベントに応答する場合、それらのタッチ イベントが元の場所で発生するのを引き続き監視することを意味します。アニメーションは、ビューの描画方法のみを変更し、それ以外は何も変更しません。

このCAAnimation方法では、ビューの基になる に追加することも必要ですCALayer。これが怖い場合は、-[UIView animateWithDuration:…]代わりにメソッドを自由に使用してください。を使用して追加の機能を利用できますCAAnimationが、慣れていない場合は、UIView アニメーションをチェーンするか、完了ブロックでリセットすることで問題ありません。実際、それが完了ブロックの主な目的の 1 つです。

では、どうぞ。アニメーションを逆にして元の値を維持する 3 つの方法。楽しみ!

于 2011-02-18T17:51:08.943 に答える
15

これが私の解決策です。2 倍の繰り返しの場合は、1.5 倍のアニメーションを作成し、最後の 0.5 倍の部分を自分で行います。

[UIView animateWithDuration:.3
                      delay:.0f
                    options:(UIViewAnimationOptionRepeat|
                             UIViewAnimationOptionAutoreverse)
                 animations:^{
                     [UIView setAnimationRepeatCount:1.5f];

                     ... animate here ...

                 } completion:^(BOOL finished) {
                         [UIView animateWithDuration:.3 animations:^{

                             ... finish the animation here ....

                         }];
                 }];

点滅なし、うまく機能します。

于 2012-07-26T13:35:19.330 に答える
0

repeatCountに物件がありますCAMediaTimingCAAnimation明示的なオブジェクトを作成し、適切に構成する必要があると思います。grow と ungrow の repeatCount は 2 になりますが、これをテストできます。

これの行は何か長いです。ただし、フレーム用と回転用の 2 つの CAAnimation オブジェクトが必要です。

CABasicAnimation *theAnimation;

theAnimation=[CABasicAnimation animationWithKeyPath:@"transform.rotation"];
theAnimation.duration=3.0;
theAnimation.repeatCount=1;
theAnimation.autoreverses=YES;
theAnimation.fromValue=[NSNumber numberWithFloat:0.0];
theAnimation.toValue=[NSNumber numberWithFloat:degreesToRadians(34)];
[theLayer addAnimation:theAnimation forKey:@"animateRotation"];

私の知る限り、2 つのアニメーション オブジェクトのプログラミングを避ける方法はありません。

于 2011-02-18T11:13:45.940 に答える