xref: /aosp_15_r20/external/accompanist/docs/navigation-animation.md (revision fa44fe6ae8e729aa3cfe5c03eedbbf98fb44e2c6)
1# Jetpack Navigation Compose Animation
2
3[![Maven Central](https://img.shields.io/maven-central/v/com.google.accompanist/accompanist-navigation-animation)](https://search.maven.org/search?q=g:com.google.accompanist)
4
5A library which provides [Compose Animation](https://developer.android.com/jetpack/compose/animation) support for [Jetpack Navigation Compose](https://developer.android.com/jetpack/compose/navigation).
6
7!!! warning
8    **This library is deprecated, with official navigation-compose support in [androidx.navigation.compose](https://developer.android.com/jetpack/compose/navigation).** The original documentation is below the migration guide.
9
10## Migration
11
12The official `androidx.navigation.compose` version 2.7.0-alpha01+ offers all of the same functionality as Accompanist Navigation Animation.
13
141. Make sure you are using Compose 1.5.0-beta01+ before migrating to `androidx.navigation.compose`.
152. Replace dependency `com.google.accompanist:accompanist-navigation-animation:<version>` with `androidx.navigation:navigation-compose:<version>`
163. Replace `rememberAnimatedNavController` with `rememberNavController` and change import to `androidx.navigation.compose.rememberNavController`
174. Replace `AnimatedNavHost` with `NavHost` and change import to `androidx.navigation.compose.NavHost`
185. Replace `AnimatedComposeNavigator` with `ComposeNavigator` and change import to `androidx.navigation.compose.ComposeNavigator`
196. Replace `AnimatedComposeNavigator()` constructor with `ComposeNavigator()` constructor
207. Replace `AnimatedComposeNavigator.Destination` with `ComposeNavigator.Destination`
218. Change import for composable from `com.google.accompanist.navigation.animation.composable` to `androidx.navigation.compose.composable`
229. Change import for navigation from `com.google.accompanist.navigation.animation.navigation` to `androidx.navigation.compose.navigation`
23
24## Migration Table
25
26The following is a mapping of Navigation classes and functions from accompanist to androidx.compose:
27
28| accompanist navigation-animation       | androidx.navigation.compose    |
29|----------------------------------------|--------------------------------|
30| `AnimatedNavHost`                      | `NavHost`                      |
31| `AnimatedComposeNavigator`             | `ComposeNavigator`             |
32| `AnimatedComposeNavigator.Destination` | `ComposeNavigator.Destination` |
33| `rememberAnimatedNavController()`      | `rememberNavController()`      |
34| `NavGraphBuilder.composable()`         | `NavGraphBuilder.composable()` |
35| `NavGraphBuilder.navigation()`         | `NavGraphBuilder.navigation()` |
36
37Of note, ComposeNavigation.Destination allows use of `AnimatedContentScope` instead of just `AnimatedVisibilityScope`.
38
39# Deprecated Guidance for Accompanist Navigation
40
41The following is the deprecated guide for using Navigation in Accompanist. Please see above migration section for how to use the `androidx.navigation.compose` Navigation.
42
43## Download
44
45[![Maven Central](https://img.shields.io/maven-central/v/com.google.accompanist/accompanist-navigation-animation)](https://search.maven.org/search?q=g:com.google.accompanist)
46
47```groovy
48repositories {
49    mavenCentral()
50}
51
52dependencies {
53    implementation "com.google.accompanist:accompanist-navigation-animation:<version>"
54}
55```
56
57Follow the steps below to either [add](#usage) Jetpack Navigation Compose to your app, or to [migrate](#migration) an existing Jetpack Navigation Compose implementation.
58
59## Usage
60
61The `AnimatedNavHost` composable offers a way to add custom transitions to composables in
62Navigation Compose via parameters that can be attached to either an individual `composable`
63destination, a `navigation` element, or to the `AnimatedNavHost` itself.
64
65Each lambda has an [`AnimatedContentScope<NavBackStackEntry>`](https://developer.android.com/reference/kotlin/androidx/compose/animation/AnimatedContentScope) receiver scope that allows you to use special transitions (such as [`slideIntoContainer`](https://developer.android.com/reference/kotlin/androidx/compose/animation/AnimatedContentScope#slideIntoContainer(androidx.compose.animation.AnimatedContentScope.SlideDirection,androidx.compose.animation.core.FiniteAnimationSpec,kotlin.Function1)) and [`slideOutOfContainer`](https://developer.android.com/reference/kotlin/androidx/compose/animation/AnimatedContentScope#slideOutOfContainer(androidx.compose.animation.AnimatedContentScope.SlideDirection,androidx.compose.animation.core.FiniteAnimationSpec,kotlin.Function1))) and gives you access to the [`initialState`](https://developer.android.com/reference/kotlin/androidx/compose/animation/AnimatedContentScope#initialState()) and [`targetState`](https://developer.android.com/reference/kotlin/androidx/compose/animation/AnimatedContentScope#targetState()) properties that let you customize what transitions are run based on what screen you are transitioning from (the `initialState`) and transitioning to (the `targetState`).
66
67- `enterTransition` controls what [`EnterTransition`](https://developer.android.com/reference/kotlin/androidx/compose/animation/EnterTransition.html) is run when the `targetState` `NavBackStackEntry` is appearing on the screen.
68- `exitTransition` controls what [`ExitTransition`](https://developer.android.com/reference/kotlin/androidx/compose/animation/ExitTransition) is run when the `initialState` `NavBackStackEntry` is disappearing from the screen.
69- `popEnterTransition` defaults to `enterTransition`, but can be overridden to provide a separate [`EnterTransition`](https://developer.android.com/reference/kotlin/androidx/compose/animation/EnterTransition.html) when the `targetState` `NavBackStackEntry` is appearing on the screen due to a pop operation (i.e., `popBackStack()`).
70- `popExitTransition` defaults to `exitTransition`, but can be overridden to provide a separate [`ExitTransition`](https://developer.android.com/reference/kotlin/androidx/compose/animation/ExitTransition) when the `initialState` `NavBackStackEntry` is disappearing from the screen due to a pop operation (i.e., `popBackStack()`).
71
72For each transition, if a `composable` destination returns `null`, the parent `navigation` element's transition will be used, thus allowing you to set a global set of transitions at the navigation graph level that will apply to every `composable` in that graph. This continues up the hierarchy until you reach the root `AnimatedNavHost`, which controls the global transitions for all destinations and nested graphs that do not specify one.
73
74Note: this means that if a destination wants to instantly jump cut between destinations, it should return [`EnterTransition.None`](https://developer.android.com/reference/kotlin/androidx/compose/animation/EnterTransition#None()) or [`ExitTransition.None`](https://developer.android.com/reference/kotlin/androidx/compose/animation/ExitTransition#None()) to signify that no transition should be run, rather than return `null`.
75
76```kotlin
77@Composable
78private fun ExperimentalAnimationNav() {
79    val navController = rememberAnimatedNavController()
80    AnimatedNavHost(navController, startDestination = "Blue") {
81        composable(
82            "Blue",
83            enterTransition = {
84                when (initialState.destination.route) {
85                    "Red" ->
86                        slideIntoContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700))
87                    else -> null
88                }
89            },
90            exitTransition = {
91                when (targetState.destination.route) {
92                    "Red" ->
93                        slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700))
94                     else -> null
95                }
96            },
97            popEnterTransition = {
98                            when (initialState.destination.route) {
99                                "Red" ->
100                                    slideIntoContainer(AnimatedContentScope.SlideDirection.Right, animationSpec = tween(700))
101                                else -> null
102                            }
103                        },
104            popExitTransition = {
105                when (targetState.destination.route) {
106                    "Red" ->
107                        slideOutOfContainer(AnimatedContentScope.SlideDirection.Right, animationSpec = tween(700))
108                    else -> null
109                }
110            }
111        ) { BlueScreen(navController) }
112        composable(
113            "Red",
114            enterTransition = {
115                when (initialState.destination.route) {
116                    "Blue" ->
117                        slideIntoContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700))
118                    else -> null
119                }
120            },
121            exitTransition = {
122                when (targetState.destination.route) {
123                    "Blue" ->
124                        slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700))
125                    else -> null
126                }
127            },
128            popEnterTransition = {
129                when (initialState.destination.route) {
130                    "Blue" ->
131                        slideIntoContainer(AnimatedContentScope.SlideDirection.Right, animationSpec = tween(700))
132                    else -> null
133                }
134            },
135            popExitTransition = {
136                when (targetState.destination.route) {
137                    "Blue" ->
138                        slideOutOfContainer(AnimatedContentScope.SlideDirection.Right, animationSpec = tween(700))
139                    else -> null
140                }
141            }
142        ) { RedScreen(navController) }
143    }
144}
145```
146
147For more examples, refer to the [samples](https://github.com/google/accompanist/tree/main/sample/src/main/java/com/google/accompanist/sample/navigation/animation).
148
149## Migration
150
151To migrate from using the Navigation Compose APIs do the following:
152
153* Replace `rememberNavController()` with `rememberAnimatedNavController()`
154* Replace `NavHost` with `AnimatedNavHost`
155* Replace `import androidx.navigation.compose.navigation` with `import com.google.accompanist.navigation.animation.navigation`
156* Replace `import androidx.navigation.compose.composable` with `import com.google.accompanist.navigation.animation.composable`
157
158Snapshots of the development version are available in [Sonatype's `snapshots` repository][snap]. These are updated on every commit.
159
160[compose]: https://developer.android.com/jetpack/compose
161[snap]: https://oss.sonatype.org/content/repositories/snapshots/com/google/accompanist/accompanist-navigation-animation/
162
163For more details see [Animations in Navigation Compose](https://medium.com/androiddevelopers/animations-in-navigation-compose-36d48870776b)
164