xref: /aosp_15_r20/external/accompanist/docs/navigation-animation.md (revision fa44fe6ae8e729aa3cfe5c03eedbbf98fb44e2c6)
1*fa44fe6aSInna Palant# Jetpack Navigation Compose Animation
2*fa44fe6aSInna Palant
3*fa44fe6aSInna Palant[![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*fa44fe6aSInna Palant
5*fa44fe6aSInna PalantA 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*fa44fe6aSInna Palant
7*fa44fe6aSInna Palant!!! warning
8*fa44fe6aSInna Palant    **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*fa44fe6aSInna Palant
10*fa44fe6aSInna Palant## Migration
11*fa44fe6aSInna Palant
12*fa44fe6aSInna PalantThe official `androidx.navigation.compose` version 2.7.0-alpha01+ offers all of the same functionality as Accompanist Navigation Animation.
13*fa44fe6aSInna Palant
14*fa44fe6aSInna Palant1. Make sure you are using Compose 1.5.0-beta01+ before migrating to `androidx.navigation.compose`.
15*fa44fe6aSInna Palant2. Replace dependency `com.google.accompanist:accompanist-navigation-animation:<version>` with `androidx.navigation:navigation-compose:<version>`
16*fa44fe6aSInna Palant3. Replace `rememberAnimatedNavController` with `rememberNavController` and change import to `androidx.navigation.compose.rememberNavController`
17*fa44fe6aSInna Palant4. Replace `AnimatedNavHost` with `NavHost` and change import to `androidx.navigation.compose.NavHost`
18*fa44fe6aSInna Palant5. Replace `AnimatedComposeNavigator` with `ComposeNavigator` and change import to `androidx.navigation.compose.ComposeNavigator`
19*fa44fe6aSInna Palant6. Replace `AnimatedComposeNavigator()` constructor with `ComposeNavigator()` constructor
20*fa44fe6aSInna Palant7. Replace `AnimatedComposeNavigator.Destination` with `ComposeNavigator.Destination`
21*fa44fe6aSInna Palant8. Change import for composable from `com.google.accompanist.navigation.animation.composable` to `androidx.navigation.compose.composable`
22*fa44fe6aSInna Palant9. Change import for navigation from `com.google.accompanist.navigation.animation.navigation` to `androidx.navigation.compose.navigation`
23*fa44fe6aSInna Palant
24*fa44fe6aSInna Palant## Migration Table
25*fa44fe6aSInna Palant
26*fa44fe6aSInna PalantThe following is a mapping of Navigation classes and functions from accompanist to androidx.compose:
27*fa44fe6aSInna Palant
28*fa44fe6aSInna Palant| accompanist navigation-animation       | androidx.navigation.compose    |
29*fa44fe6aSInna Palant|----------------------------------------|--------------------------------|
30*fa44fe6aSInna Palant| `AnimatedNavHost`                      | `NavHost`                      |
31*fa44fe6aSInna Palant| `AnimatedComposeNavigator`             | `ComposeNavigator`             |
32*fa44fe6aSInna Palant| `AnimatedComposeNavigator.Destination` | `ComposeNavigator.Destination` |
33*fa44fe6aSInna Palant| `rememberAnimatedNavController()`      | `rememberNavController()`      |
34*fa44fe6aSInna Palant| `NavGraphBuilder.composable()`         | `NavGraphBuilder.composable()` |
35*fa44fe6aSInna Palant| `NavGraphBuilder.navigation()`         | `NavGraphBuilder.navigation()` |
36*fa44fe6aSInna Palant
37*fa44fe6aSInna PalantOf note, ComposeNavigation.Destination allows use of `AnimatedContentScope` instead of just `AnimatedVisibilityScope`.
38*fa44fe6aSInna Palant
39*fa44fe6aSInna Palant# Deprecated Guidance for Accompanist Navigation
40*fa44fe6aSInna Palant
41*fa44fe6aSInna PalantThe 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*fa44fe6aSInna Palant
43*fa44fe6aSInna Palant## Download
44*fa44fe6aSInna Palant
45*fa44fe6aSInna Palant[![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*fa44fe6aSInna Palant
47*fa44fe6aSInna Palant```groovy
48*fa44fe6aSInna Palantrepositories {
49*fa44fe6aSInna Palant    mavenCentral()
50*fa44fe6aSInna Palant}
51*fa44fe6aSInna Palant
52*fa44fe6aSInna Palantdependencies {
53*fa44fe6aSInna Palant    implementation "com.google.accompanist:accompanist-navigation-animation:<version>"
54*fa44fe6aSInna Palant}
55*fa44fe6aSInna Palant```
56*fa44fe6aSInna Palant
57*fa44fe6aSInna PalantFollow the steps below to either [add](#usage) Jetpack Navigation Compose to your app, or to [migrate](#migration) an existing Jetpack Navigation Compose implementation.
58*fa44fe6aSInna Palant
59*fa44fe6aSInna Palant## Usage
60*fa44fe6aSInna Palant
61*fa44fe6aSInna PalantThe `AnimatedNavHost` composable offers a way to add custom transitions to composables in
62*fa44fe6aSInna PalantNavigation Compose via parameters that can be attached to either an individual `composable`
63*fa44fe6aSInna Palantdestination, a `navigation` element, or to the `AnimatedNavHost` itself.
64*fa44fe6aSInna Palant
65*fa44fe6aSInna PalantEach 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*fa44fe6aSInna Palant
67*fa44fe6aSInna Palant- `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*fa44fe6aSInna Palant- `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*fa44fe6aSInna Palant- `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*fa44fe6aSInna Palant- `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*fa44fe6aSInna Palant
72*fa44fe6aSInna PalantFor 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*fa44fe6aSInna Palant
74*fa44fe6aSInna PalantNote: 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*fa44fe6aSInna Palant
76*fa44fe6aSInna Palant```kotlin
77*fa44fe6aSInna Palant@Composable
78*fa44fe6aSInna Palantprivate fun ExperimentalAnimationNav() {
79*fa44fe6aSInna Palant    val navController = rememberAnimatedNavController()
80*fa44fe6aSInna Palant    AnimatedNavHost(navController, startDestination = "Blue") {
81*fa44fe6aSInna Palant        composable(
82*fa44fe6aSInna Palant            "Blue",
83*fa44fe6aSInna Palant            enterTransition = {
84*fa44fe6aSInna Palant                when (initialState.destination.route) {
85*fa44fe6aSInna Palant                    "Red" ->
86*fa44fe6aSInna Palant                        slideIntoContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700))
87*fa44fe6aSInna Palant                    else -> null
88*fa44fe6aSInna Palant                }
89*fa44fe6aSInna Palant            },
90*fa44fe6aSInna Palant            exitTransition = {
91*fa44fe6aSInna Palant                when (targetState.destination.route) {
92*fa44fe6aSInna Palant                    "Red" ->
93*fa44fe6aSInna Palant                        slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700))
94*fa44fe6aSInna Palant                     else -> null
95*fa44fe6aSInna Palant                }
96*fa44fe6aSInna Palant            },
97*fa44fe6aSInna Palant            popEnterTransition = {
98*fa44fe6aSInna Palant                            when (initialState.destination.route) {
99*fa44fe6aSInna Palant                                "Red" ->
100*fa44fe6aSInna Palant                                    slideIntoContainer(AnimatedContentScope.SlideDirection.Right, animationSpec = tween(700))
101*fa44fe6aSInna Palant                                else -> null
102*fa44fe6aSInna Palant                            }
103*fa44fe6aSInna Palant                        },
104*fa44fe6aSInna Palant            popExitTransition = {
105*fa44fe6aSInna Palant                when (targetState.destination.route) {
106*fa44fe6aSInna Palant                    "Red" ->
107*fa44fe6aSInna Palant                        slideOutOfContainer(AnimatedContentScope.SlideDirection.Right, animationSpec = tween(700))
108*fa44fe6aSInna Palant                    else -> null
109*fa44fe6aSInna Palant                }
110*fa44fe6aSInna Palant            }
111*fa44fe6aSInna Palant        ) { BlueScreen(navController) }
112*fa44fe6aSInna Palant        composable(
113*fa44fe6aSInna Palant            "Red",
114*fa44fe6aSInna Palant            enterTransition = {
115*fa44fe6aSInna Palant                when (initialState.destination.route) {
116*fa44fe6aSInna Palant                    "Blue" ->
117*fa44fe6aSInna Palant                        slideIntoContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700))
118*fa44fe6aSInna Palant                    else -> null
119*fa44fe6aSInna Palant                }
120*fa44fe6aSInna Palant            },
121*fa44fe6aSInna Palant            exitTransition = {
122*fa44fe6aSInna Palant                when (targetState.destination.route) {
123*fa44fe6aSInna Palant                    "Blue" ->
124*fa44fe6aSInna Palant                        slideOutOfContainer(AnimatedContentScope.SlideDirection.Left, animationSpec = tween(700))
125*fa44fe6aSInna Palant                    else -> null
126*fa44fe6aSInna Palant                }
127*fa44fe6aSInna Palant            },
128*fa44fe6aSInna Palant            popEnterTransition = {
129*fa44fe6aSInna Palant                when (initialState.destination.route) {
130*fa44fe6aSInna Palant                    "Blue" ->
131*fa44fe6aSInna Palant                        slideIntoContainer(AnimatedContentScope.SlideDirection.Right, animationSpec = tween(700))
132*fa44fe6aSInna Palant                    else -> null
133*fa44fe6aSInna Palant                }
134*fa44fe6aSInna Palant            },
135*fa44fe6aSInna Palant            popExitTransition = {
136*fa44fe6aSInna Palant                when (targetState.destination.route) {
137*fa44fe6aSInna Palant                    "Blue" ->
138*fa44fe6aSInna Palant                        slideOutOfContainer(AnimatedContentScope.SlideDirection.Right, animationSpec = tween(700))
139*fa44fe6aSInna Palant                    else -> null
140*fa44fe6aSInna Palant                }
141*fa44fe6aSInna Palant            }
142*fa44fe6aSInna Palant        ) { RedScreen(navController) }
143*fa44fe6aSInna Palant    }
144*fa44fe6aSInna Palant}
145*fa44fe6aSInna Palant```
146*fa44fe6aSInna Palant
147*fa44fe6aSInna PalantFor more examples, refer to the [samples](https://github.com/google/accompanist/tree/main/sample/src/main/java/com/google/accompanist/sample/navigation/animation).
148*fa44fe6aSInna Palant
149*fa44fe6aSInna Palant## Migration
150*fa44fe6aSInna Palant
151*fa44fe6aSInna PalantTo migrate from using the Navigation Compose APIs do the following:
152*fa44fe6aSInna Palant
153*fa44fe6aSInna Palant* Replace `rememberNavController()` with `rememberAnimatedNavController()`
154*fa44fe6aSInna Palant* Replace `NavHost` with `AnimatedNavHost`
155*fa44fe6aSInna Palant* Replace `import androidx.navigation.compose.navigation` with `import com.google.accompanist.navigation.animation.navigation`
156*fa44fe6aSInna Palant* Replace `import androidx.navigation.compose.composable` with `import com.google.accompanist.navigation.animation.composable`
157*fa44fe6aSInna Palant
158*fa44fe6aSInna PalantSnapshots of the development version are available in [Sonatype's `snapshots` repository][snap]. These are updated on every commit.
159*fa44fe6aSInna Palant
160*fa44fe6aSInna Palant[compose]: https://developer.android.com/jetpack/compose
161*fa44fe6aSInna Palant[snap]: https://oss.sonatype.org/content/repositories/snapshots/com/google/accompanist/accompanist-navigation-animation/
162*fa44fe6aSInna Palant
163*fa44fe6aSInna PalantFor more details see [Animations in Navigation Compose](https://medium.com/androiddevelopers/animations-in-navigation-compose-36d48870776b)
164