iOSにおけるカスタムトランジションの実装
既存のpresentやpushにはアニメーションが実装されていますが、もう少し遅くしたいかもしれません。また、TabBarを用いた画面切り替えにはそもそもアニメーション自体が付いていません。アプリ全体の雰囲気を高めるためにも、遷移時アニメーションをカスタマイズしたい場合があります。
UIViewControllerTransitioningDelegate
を用いたカスタムトランジションは、以下の2ステップで実装できます:
- Animatorの作成
- 作成したAnimatorの指定
1. Animatorの作成
UIViewControllerAnimatedTransitioning
を継承したオブジェクトを作成します。ここにアニメーションのdurationと挙動を記述します。
2. 作成したAnimatorの指定
デリゲートメソッドにて、先ほど作成したAnimatorを指定します。
A. present/dismissの場合
遷移先のviewControllerにUIViewControllerTransitioningDelegate
を継承し、指定のメソッドにてAnimatorを指定します。
遷移をコードで書く場合には遷移元に記述しますのでtransitionDelegate
も同じところに書いてしまいそうになりますが、このデリゲートは自分自身がpresentされる時やdismissされる時のAnimatorを指定するものです。なので、遷移先に継承させます。
B. push/popの場合
自作のUINavigationController
クラスにUINavigationControllerDelegate
を継承し、指定のメソッドにてAnimatorを指定します。
C. TabBarの場合
自作のUITabBarController
クラスにUITabBarControllerDelegate
を継承し、指定のメソッドにてAnimatorを指定します。
UIViewControllerContextTransitioningとは
UIViewControllerContextTransitioning
とは、UIKitによって構成されるオブジェクトが準拠しているプロトコルです。私たちが生成することはなく、AnimatorのanimateTransition:
とtransitionDuration:
で引数として渡されます。主にanimateTransition:
内でアニメーションの詳細を記述する際に使用します。この中には遷移に関連するviewとviewControllerが含まれていて、以下のように取得することができます:
ただ、これから行うトランジションのpresent/dismissやpush/popを判別できる情報はこのオブジェクトには含まれていません。そのためトランジションによってアニメーションを切り替えたい場合には、先述の 2. 作成したAnimatorの指定 にてAnimatorを生成する際に、必要な情報を渡します。
UIViewControllerContextTransitioningの注意点3つ
- 遷移先のビューを
containerView
に追加する
UIViewControllerContextTransitioning
はcontainerView
というビューを持っており、これがアニメーション中のsuperviewとして振る舞います。全ての遷移アニメーションはこのビューの上で行われます。遷移元のビューはUIKitによって自動的に追加されていますが、遷移先のビューはanimateTransition:
内でaddSubviewする必要があります。
2. アニメーションでかけた加工は元に戻す
UIViewControllerContextTransitioning
内のviewやviewControllerは、スナップショットではなく本物です。そのため、アニメーション終了後にはこれらにかけた加工を元に戻す処理を書く必要があります。
3. アニメーション終了時にはcompleteTransition(_:)
を呼び出す
また、アニメーションの終了時には必ずcompleteTransition(_:)
を呼び出さなければいけません。これもアニメーションのcompletionHandlerの中に記述しましょう。
以上でカスタムトランジションの実装は終了です。ビュー全体をアニメーションさせるだけでなく、特定の部品からズームイン/アウトするような遷移も作ることができます。また、Animatorに準拠させるプロトコルを変えることで、インタラクティブな遷移も実装することができます。
サンプルコードはこちら
参考文献