2011年7月10日日曜日

iPhoneアプリ開発-画面遷移のアニメーション

前回、設定画面ではフリップのアニメーションで画面遷移することが多いみたい と書きましたが、
実際どんなことが標準で用意されているのか?をまとめてみたいと思います。

画面遷移で行える以下のパターンを説明します。
1. 子階層のレベルの画面に遷移
2. 兄弟階層のレベルの画面に遷移
3. 全く違う画面に遷移(設定画面など)

1. 子階層レベルの画面に遷移

子階層に移動するには UINavigationController を使って遷移していきます。
UINavigationControllerの標準の動きは "右から左の方向へ push" することにより遷移していきます。

実際のコードはこれ。
[self.navigationController pushViewController:myController animated:YES];

これを使うと、NavigationBar (画面上部のヘッダ部分) が引き継がれ、
左のボタンは、前画面へ戻るボタンが自動的に追加されます。
ボタン名称は、前画面の画面タイトル(Navigationのタイトル)になります。

子階層の画面に遷移するときは、これ以外の動きのパターンは基本使わないかな..と思います。
が、スライド動作で、親画面にもどる 動作をコードで追加したい場合とか自分で組み込みたくなるときがあります。
そんな場合は、私はCATransitionを使っています。

CATransition *transition = [CATransition animation];
transition.duration = 0.4;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
[self.navigationController.view.layer addAnimation:transition forKey:nil];
[self.navigationController pushViewController:setting animated:YES];

上記の例は "左から右へ push" です。
設定は type と subtype があり、
typeは
kCATransitionFade
kCATransitionMoveIn
kCATransitionPush
kCATransitionReveal
subtypeは
kCATransitionFromRight
kCATransitionFromLeft
kCATransitionFromTop
kCATransitionFromBottom
があります。組み合わせでかなり細かく設定できますね。

※ただ、これ以外にもっと楽な方法が有りそうな気もしなくもない... もっとよい方法があれば教えてください!
※CATransition ですが QuartzCore に入っているので、ライブラリを設定し、#import でインポートしておく必要があります。

2. 兄弟階層のレベルの画面に遷移

この場合は、コンテンツの内容により、画面遷移のアニメーションは変わる可能性があります。
前画面が一覧画面で、現画面がその詳細画面 という場合には、
前のコンテンツへの移動は 上から下へのpush
次のコンテンツへの移動は 下から上へのpush
が自然な気がします。

また、本の1ページのイメージの画面では
前のページへの移動は 左から右へのpush
前のページへの移動は 右から左へのpush
が自然ですね。

このパターンの場合、画面のレイアウトは同じで、中身のコンテンツ(文字列とか)を再描画し直すというパターンが多いかと思います。
そんなときは画面遷移とは言わないかもしれませんがw

Viewを単純に切り替えたい場合は、アニメーションは独自でゴリゴリ書くときもあるとおもいますが、表示中のViewに対して addSubView してあげる感じでしょうか。
その場合のアニメーションの指定は、前述のCATransitionが使えます。

CATransition *transition = [CATransition animation];
transition.duration = 0.4;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
[self.navigationController.view.layer addAnimation:transition forKey:nil];
[self.view addSubview:myController.view];

この場合、NavigationBarは同じものが表示されます。

3. 全く違う画面に遷移(設定画面など)

設定画面などは現在表示しているコンテンツとは全く違う情報を表示することになります。
どんなパターンがあるか...はアプリによりますが、設定画面のようなものと仮定すると、モーダル画面として使う事になるのがほとんどなのでそのパターンで説明します。

その場合は、NavigationController の
[self.navigationController presentModalViewController:myController animated:YES];
を使用します。
標準の動きは "下から上へのpush" です。
このアニメーションを変えるには、このコードの前に遷移先のViewControllerに対して modalTransitionStyle を設定します。
modalTransitionStyle は 以下の種類があります。

UIModalTransitionStyleCoverVertical : 下から上へのpush
UIModalTransitionStyleFlipHorizontal : フリップ (画面がくるっと回りながら遷移)
UIModalTransitionStyleCrossDissolve : ディゾルブ (元画面がだんだん薄くなって先画面がだんだん濃くなる)
UIModalTransitionStylePartialCurl : ページカール ※v3.2以上 (マップアプリの右下のボタンの動き)

画面遷移した後、元画面に戻る場合は、遷移先画面で
[self dismissModalViewControllerAnimated:YES];
を行います。
戻る場合にも同じようなアニメーションをかけてくれます。かしこい。

presentModalViewController を使う場合は、元々表示されていたNavigationBarは表示されなくなります。
全く違う画面が表示されるから...ですね。

でもモーダル画面でもヘッダ(NavigationBar)は表示したいというときがあります。
そのときはNavigationBarを新たに作って設定してあげます。
遷移先画面のレイアウト時に行うのではなく、NavigationControllerを作って、そのControllerで遷移をする方がスマートかと思います。

UINavigationController* navigation = [[UINavigationController alloc] initWithRootViewController:myController];
[self.navigationController presentModalViewController:navigation animated:YES];

こんな感じ。


ながながと書いてしまった。。
• • •