LIFULL Creators Blog

LIFULL Creators Blogとは、株式会社LIFULLの社員が記事を共有するブログです。自分の役立つ経験や知識を広めることで世界をもっとFULLにしていきます。

Simple Example : UINavigationControllerを使った時のView間Transition

大坪と申します。さて、長いサンプルプログラムはよくわからない。ポイントを含んでできる限り短くシンプルに、が信条のSimple Exampleシリーズ第2弾はiOS7から可能になったViewController間のTransitionです。


ここで
「ではいろいろな種類のTransitionについて一つにサンプルで」
とやるとSimple Exampleの主旨から外れるので

「UINavigationControllerに対してpushViewControllerする場合に独自アニメーションをつけて遷移(transition)する」

だけの例を説明します。他の例(というかもっと丁寧な説明)はネット上にいくつか存在していますが、例えばこちらのブログ
[iOS 7] 簡単にできる画面遷移のカスタマイズ - iOS 開発ブログ Natsu's note
を参照ください。


サンプルプログラムはgithubに置きました。

起動するとこんな画面がでてきます。

あまりの色彩センスの良さにめまいがするかもしれませんが、気のせいです。これぐらいでひるんでいてはかっこいいTransitionなど実現できません。

まずオレンジの"Simple Transition"というボタンを押します。

するとこんな感じで画面が遷移します。慣れ親しんだnavigationControllerにpushViewControllerすればこうなるわな、という動きです。

次に赤い"Magnify Transition"というボタンを押してみます。

すると、ずりずりと中央から黄色い画面が広がる。それと同時にナビゲーションバーに"< Back"という文字が出てきます。

その文字をを押すと黄色い画面が縮小していき、後ろに青い(最初に見えた)画面が出てくる。iOS7から可能になったView間Transitionのカスタマイズ機能を使うことこういうことができるわけです。


さて、この動きの実現方法ですが...

まず"Simple Transition"のほうです。ViewController.mを見ましょう。Simple Transitionボタンを押すと以下のコードが実行されます。

Pushされる(つまり次に表示される)ViewControllerを作ってPushしている。普通のコードですが、その間に謎の「//delegateをクリアする」

という行が入っています。

なんとなく不安を覚えながらも、"Magnify Transition"を押した時に実行される部分を見てみます。

ViewController.mの-(void) magnifyButtonPushed:(id)senderですが。。

なんださっきと変わらないじゃないかと思われるかもしれません。実際違うのは一行だけで

self.navigationController.delegate = _transitioningDelegate;

ここだけです。(Simple Transitionではnilをセットしていた)

この_transitionDelegateは-(void) viewDidLoadの中で[TransitionDelegate new]として作成しています。

ではこのTransitionDelegateは何をしているかと言えばmethodは一つしか無く

これだけです。if文の中身は見なかったことにして、やっていることは大枠

「MagAnimTransitionを作って返す」

ということ。であれば、MagAnimTransitionがあれこれややこしいことをやっているに違いない。というわけでMagAnimTransition.mの- (void)animateTransition:(id)transitionContext を見てみましょう。

.....

と書いておいてなんなのですが、このメソッドの中をちゃんと説明しだすととても長くなるので、ソースを見てください。(ちょびっとコメントも書いてあります)先ほど見なかったことにしたif文は、「行きと帰り」でアニメーションがちょっと違うのでそれを区別するためのフラグをたてていたのでした。

「行き」だけコードに沿って説明すると


  • まず「行き先」のViewのサイズを0にして
  • 次にそれをaddSubviewする。
  • でもってUIView animateKeyframesWithDuration:の中で「行き先」のViewサイズをアニメーション付きで戻して
  • 最後に[transitionContext completeTransition:finished]; を呼ぶ(これ必要)
                    • -

最低限これだけやれば、サンプルプログラムにあるような動きが実現できます。そもそもここにでてきたdelegateだのクラスは何をやっているのだ、ということをちゃんと調べたい方は、前述のブログあるいは他の文章を参照ください。

私はとりあえず動くコードがあってそこからあれこれいじっていく人なので、同じような調べ方をする人にとって、このサンプルが何かの参考になればと思っております。