NavDisplay provides built-in animation capabilities to create smooth
visual transitions as users navigate through your app. You can customize these
animations globally for the NavDisplay or on a per-NavEntry basis using
metadata.
Override default transitions
NavDisplay uses ContentTransforms to define how content animates during
navigation. You can override the default animation behaviors by providing
transition parameters to NavDisplay.
transitionSpec: This parameter defines theContentTransformto apply when content is added to the back stack (i.e., when navigating forward).popTransitionSpec: This parameter defines theContentTransformto apply when content is removed from the back stack (i.e., when navigating back).predictivePopTransitionSpec: This parameter defines theContentTransformto apply when content is popped using a predictive back gesture.
Override transitions at the individual NavEntry level
You can also define custom animations for specific NavEntrys using their
metadata. NavDisplay recognizes special metadata keys to apply per-entry
transitions:
NavDisplay.transitionSpec: Use this helper function to define the forward navigation animation.NavDisplay.popTransitionSpec: Use this helper function to define the backward navigation animation for a specificNavEntry.NavDisplay.predictivePopTransitionSpec: Use this helper function to define the animation for predictive back gestures for a specificNavEntry.
These per-entry metadata transitions override the NavDisplay's global
transitions of the same name.
The following snippet demonstrates both global NavDisplay transitions and an
override at the individual NavEntry level:
@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) ) } } } }