プラットフォームの画面遷移デザインからReact Nativeのナビゲーションを考える


## 目的
React Nativeのナビゲーション（画面遷移）ライブラリは、まだデファクトと言えるものがない状態です。（公式では[react-navigation](https://reactnavigation.org/)推し）
そこで、そもそもiOS/Androidアプリに求められるナビゲーションの要件は何かを再調査し、その上でライブラリ選定を行おうと考えました。

（筆者はWebは得意ですがアプリエンジニアではないので、もし間違っている事があればご指摘ください。）

## iOS

ナビゲーションについてはココにまとまっています。

https://developer.apple.com/ios/human-interface-guidelines/interaction/navigation/

> People tend to be unaware of an app’s navigation until it doesn’t meet their expectations. Your job is to implement navigation in a way that supports the structure and purpose of your app without calling attention to itself.

> （意訳）Navigationはなるべくユーザーに気づかれないように自然な遷移をすることが大切です。目的に合った遷移をしましょう。

iOSでは主に３つのパターンがあり、さらにModalなどのパターンがあります。

### Hierarchical navigation

> To go to another destination, you must retrace your steps or start over from the beginning and make different choices.

選択肢を選んで進んでいくタイプ。
もし違う方向に行きたければ来た道をすんなり戻っていくことが出来ます。
（例：Settingsアプリ。メールアプリなど）

![](https://developer.apple.com/ios/human-interface-guidelines/images/NavigationHierarchical-Graphic.png)

![settings.gif](https://qiita-image-store.s3.amazonaws.com/0/7185/3915e36b-0608-e374-cad9-b5ad9515250d.gif)


iOSでは[Navigation Bar](https://developer.apple.com/ios/human-interface-guidelines/ui-bars/navigation-bars/)で実現されていて、新しいページが右側から被さってくるような遷移をします。

- 戻るときは、左上の戻るボタンを押したり、左端から右に現在のページを押しのけるようにスワイプします

- 自分がどこにいるか、以前のページはどこなのかを画面上部のNavigation Barで示すことでユーザーにとってわかりやすくなります。

- Barの右側には操作ボタンが並ぶことがあります。
- Navigaton Barは非表示にしたり、半透明にしたりできます。

### Flat navigation

> Switch between multiple content categories. Music and App Store use this navigation style.

複数のカテゴリに移動することができます。
（例：音楽アプリ、Healthアプリなど）

![](https://developer.apple.com/ios/human-interface-guidelines/images/NavigationFlat-Graphic.png)

![health.gif](https://qiita-image-store.s3.amazonaws.com/0/7185/ac7b9fdd-22a1-979b-0dea-94358dc08ace.gif)

iOSでは[Tab Bar](https://developer.apple.com/ios/human-interface-guidelines/ui-bars/tab-bars/)で実現されていて、画面下部にそれぞれのアイコンが並んで、ボタンを押すとそこのカテゴリに遷移します。

- それぞれのタブのコンテンツは独立しています。
  - あるタブの中のボタンを押したら別のタブに移動する、は基本的にはすべきではありません。（要出典）
  - また、一度他のタブに移動してまた元のタブに戻った場合には、先程まで見ていたページと同じページが表示されているようにすべきです。（要出典）

- また、左右のスワイプで移動はできません（上記Navigation Barの「戻る」とぶつかるため？）

- キーボードなどの表示時にはタブは見えなくなるのが望ましいです。
- タブそれぞれは、任意のアイコンと文字列が並ぶことが一般的で、アイコンにはバッジが付くこともあります。
- それぞれのページの中でさらにHierarchical navigationの遷移をさせるケースが一般的によく見られます。

### Content-driven or experience-driven navigation

自由に画面遷移するタイプ。

![](https://developer.apple.com/ios/human-interface-guidelines/images/NavigationExperienceDriven-Graphic.png)

ゲームなど、ユーザーでなくアプリ側で画面制御をしたいような没入型アプリに多いようです。
例えば、マリオでは「ステージ選択」→「ステージ」→「クリア画面」→「ステージ選択」のように遷移しますが、「戻る」などの操作は許容されていないですね。
ページという単位を意識させないような挙動をするため、特にこれというツールは提供されてないように思います。
今回のナビゲーションライブラリ選定でも考慮しないことにします。

### Modal

[Modality](https://developer.apple.com/ios/human-interface-guidelines/interaction/modality/)

> Modality creates focus by preventing people from doing other things until they complete a task or dismiss a message or view. Action sheets, alerts, and activity views provide modal experiences.

他のことをさせずに、目の前のものの操作を強制したい時に使います。

[Action sheets](https://developer.apple.com/ios/human-interface-guidelines/ui-views/action-sheets/)、[Alerts](https://developer.apple.com/ios/human-interface-guidelines/ui-views/alerts/)、[Popover](https://developer.apple.com/ios/human-interface-guidelines/ui-views/popovers/)、Modal viewなどが該当します。（ここでは画面遷移に限るので、alertなどは割愛します。）

#### Modal view

ディスプレイ下部から全面を覆うように表示されるViewです。

alertなどでは対応できないようなこと（複数ページにまたがるもの、複雑な入力を要求するもの、表示内容が多いものなど）に使います。
ユーザーの操作を強制してしまうため、基本的には画面上部に「Cacnel」ボタンが付いてます。

対象とする操作が複数ページにまたがる場合は、Page ControlやNavigation Barを用いるのが一般的のようです。

### Q&A

#### 複数のタブの中で同じページを扱いたい場合

AppleStoreやiBooksアプリなんかが該当すると思います。
これらは、「オススメ」や「検索」タブの中のどちらにも、それぞれ「アプリ詳細」「書籍詳細」ページがあったりします。
この場合は、ページ自体は独立して作っておいて、いずれのタブでもそれを参照するのが良さそうです。
「それぞれのタブは独立している」が重要なため、「他のタブの該当ページに遷移する」をしてはいけません。

#### Flatなページ数が可変の場合はどうする？

タブの場合、スマホ画面であればコンテンツ数は2~5個が良いとされています。

が、例えば天気アプリでは、たくさんの地区の天気を見たかったりします。
「一覧から詳細に遷移する」でも良いのですが、複数の天気をさっと見たい時場合には「[Page Controls](https://developer.apple.com/ios/human-interface-guidelines/ui-controls/page-controls/)」を使ったりします。


## Android

基本的にはMaterial Designを参照します。

https://material.io/guidelines/

（なお、Material Designには細かくレギュレーションがありますが、本記事に関係のないと思われるものは割愛します）

各コンテンツのRoot ViewではNavigation Drawerで遷移をし、コンテンツ内での遷移はTabやStack Viewを使うのが一般的なようです。（要出典）

### 画面遷移概観

https://developer.android.com/training/design-navigation/index.html

タブレットまでサポートするとかなり画面構成が入り組んでしまうのでモバイルのみで考えますが、iOSと同じように、ベースはHierarchical navigationとFlat navigationでAndroid特有の特殊な遷移パターンはないように思います。

### Tool bar

Material Designになってからは、画面トップにTool Barを置くのが一般的なようです。
左上にはハンバーガーアイコン（Navigation Drawer）や戻るボタンを置き、右上に各種操作のDrop Downを置いたりします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/7185/1bb05d86-914f-b2e9-905b-faac8a8e1066.png)


### Navigation Drawer

https://material.io/guidelines/patterns/navigation-drawer.html

![music.gif](https://qiita-image-store.s3.amazonaws.com/0/7185/8460ee85-4655-c1c8-9a94-b534e8dc7320.gif)

左から覆いかぶさるようにNavigation用のページが出てくるパターン。
コンテンツ間のグローバルな遷移に使います。

### Stack View

https://developer.android.com/guide/components/activities/tasks-and-back-stack.html

基本的にはiOSと同じく上にかぶさってきて、Navigation BarかTool Barの戻るボタンで前のページに戻ることが出来る。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/7185/564a8524-914c-ad59-9279-b0f39f127088.png)

Material Designでは、ページ遷移をユーザーにわかりやすくするためにコンテンツに合ったCustom Transitionを実装しているものもある（Google公式のアプリ以外でちゃんとやっているものをあまり見ない。。）

https://developer.android.com/training/material/animations.html

![transition.gif](https://qiita-image-store.s3.amazonaws.com/0/7185/525b56c1-59ca-7eaa-4651-308533b189b7.gif)

### Embedded navigation

https://material.io/guidelines/patterns/navigation.html#navigation-patterns

メインとなるページがあり、そこに一部分だけかぶせるような形で別ページが入ってくる。
Navigation Barの戻るボタンを押すと引っ込む

![](https://storage.googleapis.com/material-design/publish/material_v_11/assets/0Bzhp5Z4wHba3VTk0QjZOVUxFY1k/patterns_navigation_patterns_embedded1.png)

### Tabs（画面上部）

https://material.io/guidelines/patterns/navigation.html#navigation-patterns

画面上部にタブが表示されるパターン。
タブ間の移動は横Swipeで出来る。
（そのため、タブ内のコンテンツでは横Swipeを使うコンテンツを置くべきではない）

![tab.gif](https://qiita-image-store.s3.amazonaws.com/0/7185/02c71395-8214-06c9-b74e-d544f4679dea.gif)

### Bottom navigation（Tabsの画面下部？）

https://material.io/guidelines/components/bottom-navigation.html

こちらはMaterial Designから追加されたもの。
Navigation Drawerと同じように使うようですが、項目が少ない時にはこちらのほうがわかりやすいという使い分けなのかも。

[Bottom navigationの使いどころを整理する](http://qiita.com/konifar/items/d64ada9c8ce069e6d138)

## React Nativeでのライブラリ選定

長くなってしまったので別記事で紹介します。
取り上げる予定のものは、

- [react-navigation](https://reactnavigation.org/)
- [react-native-navigation](https://github.com/wix/react-native-navigation)
の予定です。