Navigation Component Codelabメモ

自分用メモ。Codelabを進めながら箇条書きした >> [Navigation Codelab](https://codelabs.developers.google.com/codelabs/android-navigation/index.html?index=..%2F..%2Findex#0)

# 1. Introduction
- Navigation Architecture Componentはアプリで絶対に必要となるナビゲーションを簡単にしてくれるライブラリ
- 取り入れることで得られるメリット
    - Fragment Transactionのハンドリングが楽になる
    - Upボタン、Backボタンの正しい振る舞いを取り入れられる
    - デフォルト遷移アニメーションが含まれている
    - ディープリンク操作の手厚いサポート
    - ちょっと付け加えるだけで`Navigation Drawer`、`Bottom Navigation`と連携できる
    - 遷移時の値の受け渡しを`Type Safe`に行える
    - GUIで遷移を組める
- 実際にCodelabでやること
    - 定義済、イベントをハンドリングしての遷移の実装
    - `Sub Navigation`
    - `Menu Navigation`
    - `Bottom Navigation`
    - `deeplink`

# 2. Setup Your Environment
省略

# 3. Introducing the Navigation Graph
- 「アプリユーザが遷移可能な画面」をきちんと定義することが大切。
- ↑を`destination`と呼ぶ
- `Navigation Component`を使用すれば、`Fragment destination`の定義がよく出る
- `Activity`の`destination`の定義もできる
- 必要とあれば`Activity`、`Fragment`以外もサポート可能（[Add support for new destination types](https://developer.android.com/topic/libraries/architecture/navigation/navigation-add-new)）

## Navigation Graph
- 画面遷移は`Navigation Graph`で視覚的に表せる
- ユーザの到達しうる画面を全てここに定義する
- `Navigation Editor`を使えば容易に確認、定義できる

## Exploring the Navigation Editor
1. `res/navigation/hogehoge.xml`を開く
2. Designタブにすると確認できる

- `destination`間に引かれる線を`action`と呼ぶ

## Anatomy of a navigation XML file（navigation xmlの詳細）
- `<navigation>`がrootとなる
- `<navigation>` には、1つまたは複数の宛先が含まれる
- `app:startDestination`で、アプリを開いたときにデフォルトで起動される`destination`を指定する
- `android:id` でidを定義
- `android:name` で、その`destination`に到達したときにインスタンス化する`Fragment`を定義
- `tools:layout` で、開発中に参照するレイアウトファイルを定義できる

# 4. Add a Destination to the Navigation Graph
- `destination`を追加するボタンをクリックして、`Fragmnet`を選択して追加する

# 5. Using the Navigation Graph to Navigate
## Activities and Navigation
- ナビゲーションの原則として`Bottom Navigation`などのグローバルナビゲーションを含むアプリのエントリポイントとしての`Activity`があることが奨励されている
- 対して`Fragment`は`Activity`の中の実際のレイアウトになる
- 原則を踏襲するために`NavHostFragment`をアプリに入れる必要あり
- `NavHostFragment`は`destination`を入れ替え出しするための箱
- `android:name="androidx.navigation.fragment.NavHostFragment"`, `app:defaultNavHost="true"`を定義することで戻るボタンと挙動を統一できる
- `app:navGraph="@navigation/hogehoge"` で`avHostFragment`と`Navigation Graph`を関連付ける

## NavigationController
- ボタンクリックをトリガーにして画面遷移させたい場合、このクラスを使う
- `NavController`クラスがあり、`NavHostFragment`のFragment切り替えを行うことができる
- `NavController`は以下のstatic関数で取得できる
    - `Navigation.findNavController(activity: Activity, @Idres viewId: Int)`
    - `Navigation.findNavController(view: View)`
    - `NavHostFragment.findNavController(fragment: Fragment)`
    - `View.findNavController()`
- ボタンクリック時に遷移させたいというときには、`Navigation.createNavigateOnClickListener(@IdRes destId: Int, bundle: Bundle)`

# 6. Change the Navigation Transition
- `navigate(...)`は、何も指定しないとTransition Animationはパチパチ切り替わるだけ
- `NavOptions`で指定してあげる

# 7. Navigate using actions
- `Navigation Graph`にて、`destination`間に描画される線を`action`と呼ぶ
- `Navigation Graph`内で`<action>`を定義していれば`Navigation.createNavigateOnClickListener(R.id.next_action, null)`と、その`action`を指定するだけでTransition Animationを利用できる

# 8. Navigating using menus, drawers and bottom navigation
- `NavigationUI`...現在の`NavigationGraph`上の`destination`と同じIDを持つメニューがあれば、そのメニューをタップすると対象の`destination`に遷移するようになる

# 9. [Optional] Using type safe argument bundles for navigation
- `app/build.gradle`に`apply plugin: 'androidx.navigation.safeargs'`を追加する
- `Navigation Graph`内に`<argument>`を追記
- `...Args`クラスができるみたい

# 10. Deep Linking to a destination
- Navigation Componentは`deep link`もサポートしている
- `NavDeepLinkBuilder`使えばOK

> By default NavDeepLinkBuilder will start your launcher Activity. You can override this behavior by passing in an activity as the context or set an explicit activity class via setComponentName().

- Deeplink時にどのようにしてBackstackがつまれるか
    - `Navigation Graph`から決定される
    - 親Activityが定義されている場合、その`Activity`もBackstackにつまれる

# 11. Associating a web link with a destination
- 今までは`intent-filter`でweb linkをハンドリングしていたが、`Navigation Graph`の`destination`に定義することでweb linkをハンドリングする
    - `<nav-graph>`を`AndroidManifest.xml`に追加する
- `<deeplink>`を`destination`に追加する
    - `app:url`属性が必要
- URLのパターンマッチなど以下をサポートしている
    - `http` or `https`のスキーマは指定しなくともやってくれる
    - `{hogehoge}`をプレースホルダーとして使える、１文字以上とマッチする
        - 格納されるStringの値は、`Bundle`から同じkeyで取り出せる
    - `.*`を使って0文字以上の文字を照合できる
    - `NavController`は`ACTION_VIEW`を自動で検知し、一致するものを探す

# 12. [Optional] Try navigating on your own
- 自分の力で頑張って！って書いてある

# 13. Congratulations!
- 終わり