Jetpack Composeでナビゲーションアニメーションの作成

#### Compose を使用したナビゲーション:
Navigation は、アプリ内のあるデスティネーションから別のデスティネーションにナビゲートできるようにする Jetpack ライブラリです。Navigation ライブラリには、Jetpack Compose による一貫性のある自然なナビゲーションを可能にする具体的なアーティファクトも用意されています。

#### 設定:
Compose をサポートするには、アプリ モジュールの build.gradle ファイルで次の依存関係を使用します。

```build.gradle.kts
dependencies {

  //https://developer.android.com/jetpack/androidx/releases/navigation
    implementation("androidx.navigation:navigation-compose:2.7.5")
}

```

#### 画面デスティネーション:
``` ScreenDestinations.kt ``` ナビゲーショングラフを作成する。
https://gist.github.com/ihridoydas/331ab66955e84b826ea168c790360639

```ScreenDestinations.kt
sealed class ScreenDestinations(val route: String) {
     object HomeScreen : ScreenDestinations("home_screen")
     object ViewScreen : ScreenDestinations("view_screen")
}
```
#### ナビグラフビルダー:
```NavGraphBuilder.kt``` グラフの構築に使用されるビルダー
https://gist.github.com/ihridoydas/31e6e459a39b0f29ffb275a921c6eab1

```NavGraphBuilder.kt
@ExperimentalAnimationApi
fun NavGraphBuilder.screen(
    route: String,
    arguments: List<NamedNavArgument> = listOf(),
    content: @Composable AnimatedVisibilityScope.(NavBackStackEntry) -> Unit
) {
    val animSpec: FiniteAnimationSpec<IntOffset> = tween(500, easing = FastOutSlowInEasing)

    composable(
        route,
        arguments = arguments,
        enterTransition = {
            slideInHorizontally(
                initialOffsetX = { screenWidth -> screenWidth },
                animationSpec = animSpec
            )
        },
        popEnterTransition = {
            slideInHorizontally(
                initialOffsetX = { screenWidth -> -screenWidth },
                animationSpec = animSpec
            )
        },
        exitTransition = {
            slideOutHorizontally(
                targetOffsetX = { screenWidth -> -screenWidth },
                animationSpec = animSpec
            )
        },
        popExitTransition = {
            slideOutHorizontally(
                targetOffsetX = { screenWidth -> screenWidth },
                animationSpec = animSpec
            )
        },
        content = content
    )
}

```

#### ナビホスト: (ネストグラフを NavHost に追加する)
```NavHost.kt``` グラフの構築に使用されるビルダー
https://gist.github.com/ihridoydas/5df933e1a6ebbbce44dd321d7bf62067
デスティネーションをネストグラフにグループ化して、アプリの UI 内の特定のフローをモジュール化できます。その例として、自己完結型のログインフローがあります。

ネストグラフはデスティネーションをカプセル化します。ルートグラフと同様、ネストグラフには、ルートによって開始デスティネーションとして識別されるデスティネーションが必要です。これは、ネストグラフに関連付けられたルートに移動するときに誘導されるデスティネーションです。

```NavHost.kt
@OptIn(ExperimentalAnimationApi::class)
@Composable
fun MainAnimationNavHost(
    navController: NavHostController,
    startDestination: String = ScreenDestinations.HomeScreen.route,
) {
    NavHost(
        navController = navController,
        startDestination = startDestination,
    ) {
        screen(ScreenDestinations.HomeScreen.route) {
            HomeScreen(navController = navController)
        }
        screen(ScreenDestinations.ViewScreen.route) {
            ViewScreen(
                navController = navController,
                onBackPress = {
                //navigateTo のためNavHostControllerを作成します。
                    navController.navigateTo(ScreenDestinations.HomeScreen.route)
                })
        }


    }
    //Back Handler
    BackHandler {
        navController.popBackStack()
    }

}
```
#### ナビホストコントローラー:
```NavHostController.kt``` 
https://gist.github.com/ihridoydas/1b5c45c3684b46a032650d368567f776

```NavHostController.kt
fun NavHostController.navigateTo(route: String) = navigate(route) {
    popUpTo(route)
    launchSingleTop = true
}
```

それで、必要なナビゲーションコンポーネントを作成終わりました、これから画面を作成します。

#### ホーム画面:
```HomeScreen.kt```

```HomeScreen.kt
@Composable
fun HomeScreen(
    navController: NavController,
) {
    Box(modifier = Modifier.fillMaxSize()) {
        Column(
            modifier = Modifier.fillMaxSize(),
            Arrangement.Center,
            Alignment.CenterHorizontally
        ) {
            Button(
                modifier = Modifier
                    .size(300.dp, 60.dp),
                onClick = {
                    navController?.navigate(ScreenDestinations.ViewScreen.route) {
                        popUpTo(ScreenDestinations.HomeScreen.route) {
                            inclusive = false
                        }
                    }
                }) {
                Text(text = "ビュー画面へナビゲーション")
            }
        }

    }

}
```

#### ビュー画面:
```ViewScreen.kt```
```ViewScreen.kt
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ViewScreen(
    navController: NavController,
    onBackPress :()-> Unit,
) {
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text(text = "ナビゲーション") },
                navigationIcon = {
                    IconButton(
                        onClick = {
                            onBackPress()
                        },
                        modifier = Modifier
                    ) {
                        Icon(Icons.Filled.ArrowBack, contentDescription = "Back")
                    }
                }
            )
        },
        content = {
            Box (modifier = Modifier.padding(it)){
                Column (modifier = Modifier
                    .fillMaxSize()){
                }
            }

        }
    )

}
```
#### 結果：
Jetpack Composeでナビゲーションアニメーションを作成できました。

<img width="400" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619500/a70ac50e-f98a-9471-0703-284f4777398c.gif">