Zwischen Zielen animieren

NavDisplay bietet integrierte Animationsfunktionen, mit denen Sie flüssige visuelle Übergänge beim Navigieren der Nutzer durch Ihre App erstellen können. Sie können diese Animationen mithilfe von Metadaten global für die NavDisplay oder pro NavEntry anpassen.

Standardübergänge überschreiben

In NavDisplay werden ContentTransforms verwendet, um zu definieren, wie sich Inhalte während der Navigation animieren. Sie können die Standardanimationen überschreiben, indem Sie NavDisplay Übergangsparameter übergeben.

  • transitionSpec: Mit diesem Parameter wird die ContentTransform definiert, die angewendet wird, wenn dem Backstack Inhalte hinzugefügt werden (d.h. beim Vorwärtsnavigieren).
  • popTransitionSpec: Mit diesem Parameter wird die ContentTransform definiert, die angewendet wird, wenn Inhalte aus dem Backstack entfernt werden (d.h. beim Zurücknavigieren).
  • predictivePopTransitionSpec: Mit diesem Parameter wird die ContentTransform definiert, die angewendet wird, wenn Inhalte mit einer Touch-Geste für die Vorhersage der Navigation ausgegeben werden.

Übergänge auf Ebene einzelner NavEntry überschreiben

Sie können auch benutzerdefinierte Animationen für bestimmte NavEntrys mithilfe ihrer Metadaten definieren. NavDisplay erkennt spezielle Metadatenschlüssel, um Übergänge pro Eintrag anzuwenden:

  • NavDisplay.transitionSpec: Mit dieser Hilfsfunktion definieren Sie die Animation für die Vorwärtsnavigation.
  • NavDisplay.popTransitionSpec: Mit dieser Hilfsfunktion können Sie die Animationseffekte für die Rückwärtsnavigation für eine bestimmte NavEntry definieren.
  • NavDisplay.predictivePopTransitionSpec: Mit dieser Hilfsfunktion können Sie die Animation für vorausschauende Zurück-Gesten für eine bestimmte NavEntry definieren.

Diese Metadatenübergänge pro Eintrag überschreiben die globalen Übergänge von NavDisplay mit demselben Namen.

Das folgende Snippet zeigt sowohl globale NavDisplay-Übergänge als auch eine Überschreibung auf individueller NavEntry-Ebene:

@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)
                )
            }
        }
    }
}

Abbildung 1. App mit benutzerdefinierten Animationen