Animare il passaggio da una destinazione all'altra

NavDisplay fornisce funzionalità di animazione integrate per creare transizioni visive fluide mentre gli utenti navigano nella tua app. Puoi personalizzare queste animazioni a livello globale per NavDisplay o in base a NavDisplay utilizzando i metadati.NavEntry

Sostituire le transizioni predefinite

NavDisplay utilizza gli elementi ContentTransform per definire l'animazione dei contenuti durante la navigazione. Puoi ignorare i comportamenti di animazione predefiniti specificando parametri di transizione per NavDisplay.

  • transitionSpec: questo parametro definisce il valore ContentTransform da applicare quando i contenuti vengono aggiunti alla pila di navigazione a ritroso (ovvero quando si naviga in avanti).
  • popTransitionSpec: questo parametro definisce il valore ContentTransform da applicare quando i contenuti vengono rimossi dallo stack di navigazione a ritroso (ovvero quando si torna indietro).
  • predictivePopTransitionSpec: questo parametro definisce il valore ContentTransform da applicare quando i contenuti vengono visualizzati utilizzando un gesto di ritorno predetto.

Sostituire le transizioni a livello di singolo NavEntry

Puoi anche definire animazioni personalizzate per NavEntry specifici utilizzando i relativi metadati. NavDisplay riconosce chiavi dei metadati speciali per applicare transizioni per voce:

  • NavDisplay.transitionSpec: utilizza questa funzione di supporto per definire l'animazione di navigazione in avanti.
  • NavDisplay.popTransitionSpec: utilizza questa funzione di supporto per definire l'animazione di navigazione a ritroso per un NavEntry specifico.
  • NavDisplay.predictivePopTransitionSpec: utilizza questa funzione di supporto per definire l'animazione per i gesti di ritorno predittivi per un NavEntry specifico.

Queste transizioni dei metadati per voce sostituiscono le transizioni globali di NavDisplay con lo stesso nome.

Lo snippet seguente mostra sia le transizioni NavDisplay globali sia un override a livello di singolo NavEntry:

@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 animazioni personalizzate.