Navigation Architecture Component 使えそうな予感

こんにちは、m_saekiです。

Google I/O 2018で追加された[Navigation Architecture Component](https://developer.android.com/topic/libraries/architecture/navigation/)
を実装しました。

先に言わせていただきます。かなり便利です！！
今までだと、FragmentTransactionの処理が複雑難解になっていくプロジェクトをいくつも経験していましたが、**「no more fragment transaction!!!」**だそうです。
やってくれたぞGoogle様!!

何ができるかというと、名前の通りFragmentのNavigatinしてくれます！w
公式の言葉を借りると遷移処理の実装を簡単にしてくれます。
The Navigation Architecture Component simplifies the implementation of navigation in an Android app.

今回は、下記の画面構成をイメージして作っていきます。
Login画面
↓
Home画面   → Profile画面
↓
Setting画面


# 環境
Android Studio 3.2.1 (<font color="DeepPink">3.2 Preview版 必須</font>)
Kotlin

# builde.gradle

project/build.gradleの設定

``` build.gradle
dependencies {
        classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha01"

        ...
}
repositories {
        google()

        ...
}
```

app/build.gradleの設定

``` build.gradle
apply plugin: "androidx.navigation.safeargs"

dependencies {
    def nav_version = "1.0.0-alpha01"
    implementation "android.arch.navigation:navigation-fragment:$nav_version" // use -ktx for Kotlin
    implementation "android.arch.navigation:navigation-ui:$nav_version" // use -ktx for Kotlin

    ...
}
```

# Navigation Resource

### AndroidStudio3.2で新しく追加されたNavigation Resourceを追加
project内のresディレクトリで右クリック→NEW→AndroidResourceFileを選択し下記に設定しOKボタン
File name : nav_graph
Recource type : Navigation

<img width="824" alt="スクリーンショット 2018-05-25 10.56.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/237545/4c669668-6e2f-3d57-05c9-9f0d675cae47.png">

### nav_graph.xmlの編集

[Text]で表示してみるとnavigationタグは初めて見ますね！

```
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android">

</navigation>
```

[Design]で編集していきましょう。
プラス画像をクリック<img width="19" alt="スクリーンショット 2018-05-25 11.13.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/237545/ad091db8-e523-c20d-4eae-40ea83c1947d.png">
↓
Create blank distinationをクリック
↓
Fragmentの名前とかxml layoutの作成、callbackの作成とか...etc

<img width="795" alt="スクリーンショット 2018-05-25 11.16.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/237545/9da96390-a78b-5aa2-1655-0c380aade07d.png">

今回はLoginFragment,HomeFragment,ProfileFragment,SettingFragmentを作成

<img width="1195" alt="スクリーンショット 2018-05-25 11.32.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/237545/6520aff9-c060-b1e1-429b-f15a299f9ed1.png">

Navigationの遷移フローを追加していきます。
Login画面
↓
Home画面   → Profile画面
↓
Setting画面
になるようにGUIで操作していきます。
iOSのStoryboardに近いし感覚です。

<img width="1203" alt="スクリーンショット 2018-05-25 11.36.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/237545/d1e93501-a36c-d871-1765-7298ea00d8ba.png">
これで遷移フローは完成です！

# Main Activity

ここで、FragmentはNavHostFragmentを指定します。
nav_graph.xmlに定義した情報をBindしてくれるみたいですね！

``` activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <fragment
        android:id="@+id/my_nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph"/>

</android.support.constraint.ConstraintLayout>
```

``` MacinActivity.kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    override fun onSupportNavigateUp()
            = findNavController(this, R.id.my_nav_host_fragment).navigateUp()
}
```

# Fragment

クリック処理の中で次の遷移先を設定
           
```
Navigation.findNavController(view).navigate(R.id.action_loginFragment_to_homeFragment)
```
残りのFragmentも同じように実装すればOKです。

``` fragment_login.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000"
    tools:context=".LoginFragment">

    <Button
        android:id="@+id/login_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="login"/>

</FrameLayout>
```

``` LoginFragment.kt
class LoginFragment : Fragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        var view = inflater.inflate(R.layout.fragment_login, container, false)
        var button = view.findViewById<Button>(R.id.login_button);
        button.setOnClickListener { view ->
            Navigation.findNavController(view).navigate(R.id.action_loginFragment_to_homeFragment)
        }
        return view
    }
}
```

# 参考URL
https://developer.android.com/topic/libraries/architecture/navigation/navigation-implementing