LoginSignup
7

More than 5 years have passed since last update.

UIViewAnimationOptionsの複数指定 - 同時に適用できるものとできないものについて

Last updated at Posted at 2015-06-19

はじめに

UIViewAnimationOptionsですが、複数のオプションを指定したときに予想外の動きをするときがあります。
例えば、TransitionCurlUpとTransitionCurlDownを指定すると、TransitionFlipFromBottomと同じ動きになります。

example
var opt = UIViewAnimationOptions.TransitionCurlUp | UIViewAnimationOptions.TransitionCurlDown
UIView.transitionWithView(view, duration: 1.0, options: opt, animations: {
    // some code
    // ここのアニメーションはTransitionFlipFromBottomの動きになる
}, completion: { finished in
    // some code
})

そこでなぜこうなるのかをUIViewAnimationOptionsの定義を調べまとめました。

(こちらにまとめたものの簡略版です)

UIViewAnimationOptionsについて

公式ドキュメントで詳細を調べました。

そこでは、UIViewAnimationOptionsはObjective-Cで以下のように実装されていることが書いてあります。

UIViewAnimationOptions
enum {
   UIViewAnimationOptionLayoutSubviews            = 1 <<  0,
   UIViewAnimationOptionAllowUserInteraction      = 1 <<  1,
   UIViewAnimationOptionBeginFromCurrentState     = 1 <<  2,
   UIViewAnimationOptionRepeat                    = 1 <<  3,
   UIViewAnimationOptionAutoreverse               = 1 <<  4,
   UIViewAnimationOptionOverrideInheritedDuration = 1 <<  5,
   UIViewAnimationOptionOverrideInheritedCurve    = 1 <<  6,
   UIViewAnimationOptionAllowAnimatedContent      = 1 <<  7,
   UIViewAnimationOptionShowHideTransitionViews   = 1 <<  8,
   UIViewAnimationOptionOverrideInheritedOptions  = 1 <<  9,

   UIViewAnimationOptionCurveEaseInOut            = 0 << 16,
   UIViewAnimationOptionCurveEaseIn               = 1 << 16,
   UIViewAnimationOptionCurveEaseOut              = 2 << 16,
   UIViewAnimationOptionCurveLinear               = 3 << 16,

   UIViewAnimationOptionTransitionNone            = 0 << 20,
   UIViewAnimationOptionTransitionFlipFromLeft    = 1 << 20,
   UIViewAnimationOptionTransitionFlipFromRight   = 2 << 20,
   UIViewAnimationOptionTransitionCurlUp          = 3 << 20,
   UIViewAnimationOptionTransitionCurlDown        = 4 << 20,
   UIViewAnimationOptionTransitionCrossDissolve   = 5 << 20,
   UIViewAnimationOptionTransitionFlipFromTop     = 6 << 20,
   UIViewAnimationOptionTransitionFlipFromBottom  = 7 << 20,
};
typedef NSUInteger UIViewAnimationOptions;

複数指定の際に " | " を使うあたりから予想できる通り、ビット演算を利用して様々なオプションが管理されていますね。

UIViewAnimationOptionTransition~に関するものだけに焦点を当てて考えます。
これらのオプションは0~7までの数字を20ビット分左シフトしています。シフトのことは一旦おいておいて、0~7までの数字を2進数表示すると、以下のようになります。

オプション名 10進数 2進数
TransitionNone 0 000
TransitionFlipFromLeft 1 001
TransitionFlipFromRight 2 010
TransitionCurlUp 3 011
TransitionCurlDown 4 100
TransitionCrossDissolve 5 101
TransitionFlipFromTop 6 110
TransitionFlipFromBottom 7 111

これを見ると複数指定するとおかしい動きをする理由がわかります。

TransitionCurlUp | TransitionCurlDown は 011 | 100 = 111 なので TransitionFlipFromBottomになります。

この実装からわかるように基本的にTransition系のオプションを2つ以上指定することは推奨されていません。オプションの複数指定は、RepeatとTransition系のオプションを指定するという様に、違う種類のオプションを指定するときに使う必要があります。

複数指定して良いオプションについて

UIViewAnimationOptionsの詳細を理解したため、どのオプションが同時に指定できるのかが定義からわかります。

まず最初に書かれている10個のオプション(UIViewAnimationOptionLayoutSubviews ~ UIViewAnimationOptionOverrideInheritedOptions)は、2進数の1桁目から10桁目までのそれぞれの桁がそれぞれのオプションのフラグになっているので、それぞれ独立していることがわかります。したがって、複数のオプションを指定しても大丈夫です。

次に書かれているUIViewAnimationOptionCurveEaseInOut~UIViewAnimationOptionCurveLinearのオプションはTransition系のときと同様に複数指定すると想定外の動作をします。
例えば、EaseInとEaseOutを指定するとLinearになります。

(これに関してはLinearとEaseInOutを交換すると、EaseIn | EaseOut = EaseInOutになり、もし複数指定しても文字通りに動作するのでそうしたら良いのになと思います。)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7