Cómo animar entre destinos

NavDisplay proporciona capacidades de animación integradas para crear transiciones visuales suaves mientras los usuarios navegan por tu app. Puedes personalizar estas animaciones de forma global para NavDisplay o por NavEntry con metadatos.

Cómo anular las transiciones predeterminadas

NavDisplay usa ContentTransform para definir cómo se anima el contenido durante la navegación. Puedes anular los comportamientos de animación predeterminados si proporcionas parámetros de transición a NavDisplay.

  • transitionSpec: Este parámetro define el ContentTransform que se aplicará cuando se agregue contenido a la pila de actividades (es decir, cuando se navegue hacia adelante).
  • popTransitionSpec: Este parámetro define el ContentTransform que se debe aplicar cuando se quita contenido de la pila de actividades (es decir, cuando se navega hacia atrás).
  • predictivePopTransitionSpec: Este parámetro define el ContentTransform que se aplicará cuando se muestre el contenido con un gesto atrás predictivo.

Anula las transiciones a nivel de NavEntry individual

También puedes definir animaciones personalizadas para NavEntry específicos con sus metadatos. NavDisplay reconoce claves de metadatos especiales para aplicar transiciones por entrada:

  • NavDisplay.transitionSpec: Usa esta función auxiliar para definir la animación de navegación hacia adelante.
  • NavDisplay.popTransitionSpec: Usa esta función auxiliar para definir la animación de navegación hacia atrás para un NavEntry específico.
  • NavDisplay.predictivePopTransitionSpec: Usa esta función auxiliar para definir la animación de los gestos atrás predictivo para un NavEntry específico.

Estas transiciones de metadatos por entrada anula las transiciones globales de NavDisplay con el mismo nombre.

En el siguiente fragmento, se muestran las transiciones NavDisplay globales y una override a nivel de NavEntry individual:

@Serializable
data object ScreenA : NavKey

@Serializable
data object ScreenB : NavKey

@Serializable
data object ScreenC : NavKey

class AnimatedNavDisplayActivity : ComponentActivity() {

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

            Scaffold { paddingValues ->

                val backStack = rememberNavBackStack(ScreenA)

                NavDisplay(
                    backStack = backStack,
                    onBack = { backStack.removeLastOrNull() },
                    entryProvider = entryProvider {
                        entry<ScreenA> {
                            ContentOrange("This is Screen A") {
                                Button(onClick = { backStack.add(ScreenB) }) {
                                    Text("Go to Screen B")
                                }
                            }
                        }
                        entry<ScreenB> {
                            ContentMauve("This is Screen B") {
                                Button(onClick = { backStack.add(ScreenC) }) {
                                    Text("Go to Screen C")
                                }
                            }
                        }
                        entry<ScreenC>(
                            metadata = NavDisplay.transitionSpec {
                                // Slide new content up, keeping the old content in place underneath
                                slideInVertically(
                                    initialOffsetY = { it },
                                    animationSpec = tween(1000)
                                ) togetherWith ExitTransition.KeepUntilTransitionsFinished
                            } + NavDisplay.popTransitionSpec {
                                // Slide old content down, revealing the new content in place underneath
                                EnterTransition.None togetherWith
                                    slideOutVertically(
                                        targetOffsetY = { it },
                                        animationSpec = tween(1000)
                                    )
                            } + NavDisplay.predictivePopTransitionSpec {
                                // Slide old content down, revealing the new content in place underneath
                                EnterTransition.None togetherWith
                                    slideOutVertically(
                                        targetOffsetY = { it },
                                        animationSpec = tween(1000)
                                    )
                            }
                        ) {
                            ContentGreen("This is Screen C")
                        }
                    },
                    transitionSpec = {
                        // Slide in from right when navigating forward
                        slideInHorizontally(initialOffsetX = { it }) togetherWith
                            slideOutHorizontally(targetOffsetX = { -it })
                    },
                    popTransitionSpec = {
                        // Slide in from left when navigating back
                        slideInHorizontally(initialOffsetX = { -it }) togetherWith
                            slideOutHorizontally(targetOffsetX = { it })
                    },
                    predictivePopTransitionSpec = {
                        // Slide in from left when navigating back
                        slideInHorizontally(initialOffsetX = { -it }) togetherWith
                            slideOutHorizontally(targetOffsetX = { it })
                    },
                    modifier = Modifier.padding(paddingValues)
                )
            }
        }
    }
}

Figura 1. App con animaciones personalizadas.