web-dev-qa-db-ja.com

iOS8でのCGAffineTransformのアニメーションは、iOS7とは異なって見えます

UIView変換プロパティのアニメーションがiOS8とiOS6/7で異なって見える理由を見つけようとしています。

簡単な例として、iOS 8より前:

myView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, 1.57);
[UIView animateWithDuration:5 animations:^{
    myView.transform = CGAffineTransformTranslate(plane.transform, 100, 0);
}];

期待どおりの結果が得られ、「myView」は90度回転して下に移動しますが、iOS8では、翻訳がアニメーション化されると、説明が見つからないポイントから開始します(アニメーションが壊れます)。

誰かがそれの説明を知っていますか?前もって感謝します!

20
maniacus

CGAffineTransformIdentityは、ios7とios8で動作が異なります。これは、自動レイアウトとサイズクラスに関係しています。解決策は、ios7のアニメーションと競合する制約を削除することです。

// solve the constraint-animation problem
if(NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) {
    // iOS7 remove constraints that conflict with animation
    if (self.centerYAlignment != nil) {
        self.view.removeConstraint(self.centerYAlignment) //is an IBOutlet 
    }
} else {
    // iOS8 constraint animations are fine
}
5
Pbk

IOS7でもぎくしゃくした回転変換に問題がありました。回転したビューをコンテナ内にネストし、回転したビューを中央に配置することで、これを解決しました。

2
Indigon

理由はiOS8のバグだけだと思いますが、代わりにCAAnimationを使用しており、iOS8でも期待どおりに動作します。

2
AndrewK

スケーリングでも同じ問題が発生しています。回転でも同じかもしれないと思います。これを試していただけませんか?

myView.transform = CGAffineTransformConcat(myView.transform , CGAffineTransformMakeRotate(1.57));
[UIView animateWithDuration:5 animations:^{
    myView.transform = CGAffineTransformTranslate(plane.transform, 100, 0);
}];

たぶん、CGAffineTransformMakeTranslateとCGAffineTransformConcatを使用する必要もあるかもしれませんが、それもよくわかりません。

これについての最悪の部分は次のとおりです。これはiOS7で奇妙に見えるため、iOSバージョンではif/elseを実行する必要があります。これは、iOS8の前または使用時にAppleによって修正されることを願っています。リリース。

1
tobihagemann

これは完全に関連しているわけではありませんが、かなり複雑なアニメーションでCGAffineTransformScaleがiOS7でまったく機能しないことに苦労していました。私の問題は、iOS7がCGAffineTransformScaleCGAffineTransformRotateを同時に計算できないことでした。 iOS7では、最後に行ったアニメーション呼び出しだけがアニメーション化されるため、回転のみが発生していました。このバグはiOS8で修正されています。

私の解決策は、iOS7のアニメーションを単純化して、iOS8の凝ったものだけをオンにすることです。

_//Pre-animation setup:
CGFloat radians = (M_PI/180) * (-15);  //Get a human-readable number in degrees
self.badgeImage.alpha = 0;  //Start the image as invisible
self.badgeImage.transform = CGAffineTransformScale(self.badgeImage.transform, 1.5, 1.5);  //Start the image as scaled bigger than normal
if(NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) {  //See below. We will not be rotating the image in iOS7
    self.badgeImage.transform = CGAffineTransformRotate(self.badgeImage.transform, radians);  //Rotate the image if iOS8
}

//Animation Pieces:
//Fade in
[UIView animateWithDuration: 0.5
                delay:0
                options:0
                animations:^{
                    self.badgeImage.alpha = 1.0f; //Return image to opaque
                }
                completion:NULL];
//Scale with bounce
[UIView animateWithDuration: 1.1
                delay:0
                usingSpringWithDamping:0.3  //Not as good as Android's bounce interpolator, but I'll take it
                initialSpringVelocity:-1.0f //A negative velocity here makes the animation appear more like gravity than spring
                options:0
                animations:^{
                    self.badgeImage.transform = CGAffineTransformScale(self.badgeImage.transform, 0.67, 0.67);  //Return image to its original size. These arguments are relative to its current scale.
                }
                completion:NULL];
//Rotation
if(NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1) { //This second animation call negates the first one on iOS7, so remove it.
    [UIView animateWithDuration: 0.9
                    delay:0
                    options:UIViewAnimationOptionCurveEaseOut
                    animations:^{
                        self.badgeImage.transform = CGAffineTransformRotate(self.badgeImage.transform, (radians * -1)); //Rotate the image back to its original orientation if iOS8
                    }
                    completion:NULL];
}
_

もちろん、紛らわしい名前のCGAffineTransformMakeScale()関数を使用すれば、iOS7で複数の効果を組み合わせることができます。たとえば、アニメーション前の設定では、回転とスケールの両方を設定してから、呼び出しCGAffineTransformMakeScale(1,1)を設定して、画像を元のメトリックにリセットできます(MakeScaleの引数は特定のものであり、相対的-さらに混乱します!)。これは、アニメーションを「バウンス」すると回転もバウンスする上記の例のように、常に好ましいとは限りません。

0
Ben Ritter

私は、io8のサイズクラスに関係しているというPbkに同意します。 uiviewcontrollersは、デバイスの向きに応じてuitraitcollectionsを使用してサイズを変更する必要があります。それ以外の場合は、電話を横向きモードにして回転させようとすると、uiviewcontrollerが縦向きモードになります。したがって、正しい手順は、uitraitcollectionsを回転してオーバーライドすることです。

0
Lucas Chwe