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つの連続したアニメーションをプログラミングしないで解決策はありますか?
3つのオプションがあります。
-[UIView animateWithDuration:…]
メソッドを使用すると、animations
ブロックで行った変更が問題のビューにすぐに適用されます。ただし、古い値から新しい値にアニメーション化する暗黙のCAAnimation
もビューに適用されます。 CAAnimation
がビューでアクティブな場合、displayedビューは変更されますが、ビューの実際のプロパティは変更されません。
たとえば、次のようにした場合:
NSLog(@"old center: %@", NSStringFromCGPoint(someView.center));
[UIView animateWithDuration:2.0 animations: ^{ someView.center = newPoint; }];
NSLog(@"new center: %@", NSStringFromCGPoint(someView.center));
「旧センター」と「新センター」が異なることがわかります。新しい中心はすぐに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番目のオプションは、アニメーションを自動反転して、完了ブロックでビューを元の位置に戻すことです。
CGPoint oldCenter = someView.center;
[UIView animateWithDuration:2.0
delay:0
options: UIViewAnimationOptionAutoreverse
animations: ^{ someView.center = newPoint; }
completion: ^(BOOL finished) { someView.center = oldCenter; }];
ただし、これにより、アニメーションの自動反転が完了してから完了ブロックが実行されるまでの間にちらつきが発生する可能性があるため、おそらく最良の選択ではありません。
最後のオプションは、単純に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つの方法。楽しい!
これが私の解決策です。 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 ....
}];
}];
点滅しません、うまくいきます。
repeatCount
にはCAMediaTiming
プロパティがあります。明示的なCAAnimation
オブジェクトを作成し、適切に構成する必要があると思います。 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つのアニメーションオブジェクトのプログラミングを回避する方法はありません。