Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Peeling back the Layers: A Navigation3 Deep Dive

Peeling back the Layers: A Navigation3 Deep Dive

Join us as we explore the Navigation3 API surface and peel back the layers of the library via the various NavDisplay overloads. We will provide insight into the decision behind each overload, how you would use each of them, and the helper APIs that assist you in building your custom logic. This will show you how to fully take advantage of the different building blocks that Navigation3 provides.

Presented at KotlinConf in 2026.

Avatar for Marcello Galhardo

Marcello Galhardo

May 21, 2026

More Decks by Marcello Galhardo

Other Decks in Technology

Transcript

  1. Today’s agenda What's Nav3? ♦ rememberNavBackStack ♦ NavDisplay ♦ ♦

    rememberDecoratedNavEntries ♦ rememberSceneState
  2. @Serializable object Home : NavKey val backStack = rememberNavBackStack(Home) NavDisplay(

    backStack = backStack, entryProvider = entryProvider { entry<Home> { Text(“Hello World”) } } )
  3. @Serializable object Home : NavKey val backStack = rememberNavBackStack(Home) NavDisplay(

    backStack = backStack, entryProvider = entryProvider { entry<Home> { Text(“Hello World”) } } )
  4. @Serializable object Home : NavKey val backStack = rememberNavBackStack(Home) NavDisplay(

    backStack = backStack, entryProvider = entryProvider { entry<Home> { Text(“Hello World”) } } )
  5. @Serializable object Home : NavKey val backStack = rememberNavBackStack(Home) NavDisplay(

    backStack = backStack, entryProvider = entryProvider { entry<Home> { Text(“Hello World”) } } )
  6. @Serializable object Home : NavKey val backStack = rememberNavBackStack(Home) NavDisplay(

    backStack = backStack, entryProvider = entryProvider { entry<Home> { Text(“Hello World”) } } )
  7. @Serializable object Home : NavKey val backStack = rememberNavBackStack(Home) NavDisplay(

    backStack = backStack, entryProvider = entryProvider { entry<Home> { Text(“Hello World”) } } )
  8. @Serializable object Home : NavKey val backStack = rememberNavBackStack(Home) NavDisplay(

    backStack = backStack, entryProvider = entryProvider { entry<Home> { Text(“Hello World”) } } )
  9. @Serializable data object Home : NavKey @Serializable data class Profile(userId:

    String): NavKey val backStack = rememberNavBackStack(Home) Button(onClick = { backStack += Profile("me") }) { .. }
  10. @Serializable data object Home : NavKey @Serializable data class Profile(userId:

    String): NavKey val backStack = rememberNavBackStack(Home) Button(onClick = { backStack += Profile("me") }) { .. } 😱
  11. // Internal KSerializer to handle Navkey serialization on Android. val

    descriptor: SerialDescriptor val index = decodeElementIndex(descriptor) val className = decodeStringElement(descriptor, index) val serializer = serializer(Class.forName(className)) return decodeSerializableElement(descriptor, index, serializer) as T
  12. // Internal KSerializer to handle Navkey serialization on Android. val

    descriptor: SerialDescriptor val index = decodeElementIndex(descriptor) val className = decodeStringElement(descriptor, index) val serializer = serializer(Class.forName(className)) return decodeSerializableElement(descriptor, index, serializer) as T
  13. // Located in one module @Serializable sealed interface AppModuleKey :

    NavKey @Serializable data object Home : AppModuleKey @Serializable data class Profile(userId: String): AppModuleKey
  14. // Located in one module @Serializable sealed interface AppModuleKey :

    NavKey @Serializable data object Home : AppModuleKey @Serializable data class Profile(userId: String): AppModuleKey val config = SavedStateConfiguration { serializersModule = SerializersModule { polymorphic(NavKey::class) { subclassesOfSealed<AppModuleKey>() } } } val backStack = rememberNavBackStack(config, Home)
  15. fun EntryProviderScope.profileEntry() { entry<Profile> { profile -> val viewModel =

    metroViewModel<ProfileViewModel>() val uiState by viewModel.uiState.collectAsState() ProfileScreen(uiState) } }
  16. NavDisplay( backStack: List<T>, modifier: Modifier = Modifier, contentAlignment: Alignment =

    Alignment.TopStart, onBack: () -> Unit = { if (backStack is MutableList<T>) backStack.removeLastOrNull() }, entryDecorators: List<NavEntryDecorator<T>> = listOf(rememberSaveableStateHolderNavEntryDecorator()), sceneStrategy: SceneStrategy<T> = SinglePaneSceneStrategy(), sceneDecoratorStrategies: List<SceneDecoratorStrategy<T>> = emptyList(), sharedTransitionScope: SharedTransitionScope? = null, sizeTransform: SizeTransform? = null, transitionSpec: AnimatedContentTransitionScope<Scene<T>>.() -> ContentTransform = defaultTransitionSpec(), popTransitionSpec: AnimatedContentTransitionScope<Scene<T>>.() -> ContentTransform = defaultPopTransitionSpec(), predictivePopTransitionSpec: AnimatedContentTransitionScope<Scene<T>>.(Int) -> ContentTransform = defaultPredictivePopTransitionSpec(), entryProvider: (key: T) -> NavEntry<T>, ) 😱
  17. require(backStack.isNotEmpty()) { "NavDisplay backstack cannot be empty" } val entries:

    List<NavEntry> = rememberDecoratedNavEntries( backStack = backStack, entryDecorators = entryDecorators, entryProvider = entryProvider, ) NavDisplay( entries = entries, sceneStrategies = sceneStrategies, sceneDecoratorStrategies = sceneDecoratorStrategies, sharedTransitionScope = sharedTransitionScope, modifier = modifier, contentAlignment = contentAlignment, sizeTransform = sizeTransform, transitionSpec = transitionSpec, popTransitionSpec = popTransitionSpec, predictivePopTransitionSpec = predictivePopTransitionSpec, onBack = onBack, )
  18. require(backStack.isNotEmpty()) { "NavDisplay backstack cannot be empty" } val entries:

    List<NavEntry> = rememberDecoratedNavEntries( backStack = backStack, entryDecorators = entryDecorators, entryProvider = entryProvider, ) NavDisplay( entries = entries, sceneStrategies = sceneStrategies, sceneDecoratorStrategies = sceneDecoratorStrategies, sharedTransitionScope = sharedTransitionScope, modifier = modifier, contentAlignment = contentAlignment, sizeTransform = sizeTransform, transitionSpec = transitionSpec, popTransitionSpec = popTransitionSpec, predictivePopTransitionSpec = predictivePopTransitionSpec, onBack = onBack, )
  19. require(backStack.isNotEmpty()) { "NavDisplay backstack cannot be empty" } val entries:

    List<NavEntry> = rememberDecoratedNavEntries( backStack = backStack, entryDecorators = entryDecorators, entryProvider = entryProvider, ) NavDisplay( entries = entries, sceneStrategies = sceneStrategies, sceneDecoratorStrategies = sceneDecoratorStrategies, sharedTransitionScope = sharedTransitionScope, modifier = modifier, contentAlignment = contentAlignment, sizeTransform = sizeTransform, transitionSpec = transitionSpec, popTransitionSpec = popTransitionSpec, predictivePopTransitionSpec = predictivePopTransitionSpec, onBack = onBack, )
  20. Attach additional responsibilities to an object dynamically. Decorators provide a

    flexible alternative to subclassing for extending functionality. — Design Patterns: Elements of Reusable Object-Oriented Software
  21. val analyticsDecorator = NavEntryDecorator<NavKey> { entry -> val contentKey =

    entry.contentKey LifecycleStartEffect(analytics, contentKey) { val tracker = analytics.startTrackingTimeOnScreen(contentKey) onStopOrDispose { tracker.stopTrackingTimeOnScreen()} } entry.Content() }
  22. val analyticsDecorator = NavEntryDecorator<NavKey> { entry -> val contentKey =

    entry.contentKey LifecycleStartEffect(analytics, contentKey) { val tracker = analytics.startTrackingTimeOnScreen(contentKey) onStopOrDispose { tracker.stopTrackingTimeOnScreen()} } entry.Content() }
  23. NavEntryDecorator( onPop = { contentKey -> saveableStateHolder.removeState(contentKey) }, decorate =

    { entry -> saveableStateHolder.SaveableStateProvider(entry.contentKey) { entry.Content() } } )
  24. val backStack = rememberNavBackStack(config, Home) val entries = rememberDecoratedNavEntries( backStack

    = backStack, entryDecorators = listOf(rememberSaveableStateHolderNavEntryDecorator()), entryProvider = entryProvider {..} ) NavDisplay( entries = entries, )
  25. val backStack = rememberNavBackStack(config, Home) val entries = rememberDecoratedNavEntries( backStack

    = backStack, entryDecorators = listOf(rememberSaveableStateHolderNavEntryDecorator()), entryProvider = entryProvider {..} ) NavDisplay( entries = entries, )
  26. val backStack = rememberNavBackStack(config, Home) val entries = rememberDecoratedNavEntries( backStack

    = backStack, entryDecorators = listOf(rememberSaveableStateHolderNavEntryDecorator()), entryProvider = entryProvider {..} ) NavDisplay( entries = entries, )
  27. val backStack = rememberNavBackStack(config, Home) val entries = rememberDecoratedNavEntries( backStack

    = backStack, entryDecorators = listOf(rememberSaveableStateHolderNavEntryDecorator()), entryProvider = entryProvider {..} ) NavDisplay( entries = entries, )
  28. val backStack = rememberNavBackStack(config, Home) val entries = rememberDecoratedNavEntries( backStack

    = backStack, entryDecorators = listOf(rememberSaveableStateHolderNavEntryDecorator()), entryProvider = entryProvider {..} ) NavDisplay( entries = entries, onBack = { backStack.removeLastOrNull() } )
  29. val homeBackStack = rememberNavBackStack(config, Home) val chatBackStack = rememberNavBackStack(config, ChatList)

    var selectedTab by remember { mutableStateOf(HomeTab) } NavDisplay( backStack = when (selectedTab) { is HomeTab -> homeBackStack is ChatTab -> chatBackStack }, //.. )
  30. val homeBackStack = rememberNavBackStack(config, Home) val homeEntries = rememberDecoratedNavEntries(homeBackStack, entryProvider,

    entryDecorators = listOf(rememberSaveableStateHolderNavEntryDecorator()), ) val chatBackStack = rememberNavBackStack(config, ChatList) val chatEntries = rememberDecoratedNavEntries(chatBackStack, entryProvider, entryDecorators = listOf(rememberSaveableStateHolderNavEntryDecorator()), ) var selectedTab by remember { mutableStateOf(HomeTab) } NavDisplay( entries = when (selectedTab) { is HomeTab -> homeEntries is ChatTab -> chatEntries }, onBack = { when (selectedTab) { is HomeTab -> homeBackStack.removeLastOrNull() is ChatTab -> chatBackStack.removeLastOrNull() )
  31. val homeBackStack = rememberNavBackStack(config, Home) val homeEntries = rememberDecoratedNavEntries(homeBackStack, entryProvider,

    entryDecorators = listOf(rememberSaveableStateHolderNavEntryDecorator()), ) val chatBackStack = rememberNavBackStack(config, ChatList) val chatEntries = rememberDecoratedNavEntries(chatBackStack, entryProvider, entryDecorators = listOf(rememberSaveableStateHolderNavEntryDecorator()), ) var selectedTab by remember { mutableStateOf(HomeTab) } NavDisplay( entries = when (selectedTab) { is HomeTab -> homeEntries is ChatTab -> chatEntries }, onBack = { when (selectedTab) { is HomeTab -> homeBackStack.removeLastOrNull() is ChatTab -> chatBackStack.removeLastOrNull() )
  32. NavDisplay( entries: List<NavEntry<T>>, modifier: Modifier = Modifier, contentAlignment: Alignment =

    Alignment.TopStart, sceneStrategies: List<SceneStrategy<T>> = listOf(SinglePaneSceneStrategy()), sceneDecoratorStrategies: List<SceneDecoratorStrategy<T>> = emptyList(), sharedTransitionScope: SharedTransitionScope? = null, sizeTransform: SizeTransform? = null, transitionSpec: AnimatedContentTransitionScope<Scene<T>>.() -> ContentTransform = defaultTransitionSpec(), popTransitionSpec: AnimatedContentTransitionScope<Scene<T>>.() -> ContentTransform = defaultPopTransitionSpec(), predictivePopTransitionSpec: AnimatedContentTransitionScope<Scene<T>>.(@NavigationEvent.SwipeEdge Int) -> ContentTransform = defaultPredictivePopTransitionSpec(), onBack: () -> Unit, )
  33. NavDisplay( entries: List<NavEntry<T>>, modifier: Modifier = Modifier, contentAlignment: Alignment =

    Alignment.TopStart, sceneStrategies: List<SceneStrategy<T>> = listOf(SinglePaneSceneStrategy()), sceneDecoratorStrategies: List<SceneDecoratorStrategy<T>> = emptyList(), sharedTransitionScope: SharedTransitionScope? = null, sizeTransform: SizeTransform? = null, transitionSpec: AnimatedContentTransitionScope<Scene<T>>.() -> ContentTransform = defaultTransitionSpec(), popTransitionSpec: AnimatedContentTransitionScope<Scene<T>>.() -> ContentTransform = defaultPopTransitionSpec(), predictivePopTransitionSpec: AnimatedContentTransitionScope<Scene<T>>.(@NavigationEvent.SwipeEdge Int) -> ContentTransform = defaultPredictivePopTransitionSpec(), onBack: () -> Unit, )
  34. require(entries.isNotEmpty()) { "NavDisplay entries cannot be empty" } val sceneState

    = rememberSceneState(entries, strategies, decoratorStrategies, sharedTransitionScope, onBack) // Predictive Back Handling val navigationEventState = rememberNavigationEventState(sceneState) NavigationBackHandler(sceneState, navigationEventState, onBackCompleted = onBack) NavDisplay( sceneState, navigationEventState, modifier, contentAlignment, sizeTransform, transitionSpec, popTransitionSpec, predictivePopTransitionSpec, )
  35. require(entries.isNotEmpty()) { "NavDisplay entries cannot be empty" } val sceneState

    = rememberSceneState(entries, strategies, decoratorStrategies, sharedTransitionScope, onBack) // Predictive Back Handling val navigationEventState = rememberNavigationEventState(sceneState) NavigationBackHandler(sceneState, navigationEventState, onBackCompleted = onBack) NavDisplay( sceneState, navigationEventState, modifier, contentAlignment, sizeTransform, transitionSpec, popTransitionSpec, predictivePopTransitionSpec, )
  36. require(entries.isNotEmpty()) { "NavDisplay entries cannot be empty" } val sceneState

    = rememberSceneState(entries, strategies, decoratorStrategies, sharedTransitionScope, onBack) // Predictive Back Handling val navigationEventState = rememberNavigationEventState(sceneState) NavigationBackHandler(sceneState, navigationEventState, onBackCompleted = onBack) NavDisplay( sceneState, navigationEventState, modifier, contentAlignment, sizeTransform, transitionSpec, popTransitionSpec, predictivePopTransitionSpec, )
  37. require(entries.isNotEmpty()) { "NavDisplay entries cannot be empty" } val sceneState

    = rememberSceneState(entries, strategies, decoratorStrategies, sharedTransitionScope, onBack) // Predictive Back Handling val navigationEventState = rememberNavigationEventState(sceneState) NavigationBackHandler(sceneState, navigationEventState, onBackCompleted = onBack) NavDisplay( sceneState, navigationEventState, modifier, contentAlignment, sizeTransform, transitionSpec, popTransitionSpec, predictivePopTransitionSpec, )
  38. require(entries.isNotEmpty()) { "NavDisplay entries cannot be empty" } val sceneState

    = rememberSceneState(entries, strategies, decoratorStrategies, sharedTransitionScope, onBack) // Predictive Back Handling val navigationEventState = rememberNavigationEventState(sceneState) NavigationBackHandler(sceneState, navigationEventState, onBackCompleted = onBack) NavDisplay( sceneState, navigationEventState, modifier, contentAlignment, sizeTransform, transitionSpec, popTransitionSpec, predictivePopTransitionSpec, )
  39. data class SinglePaneScene<T : Any>( override val key: Any, val

    entry: NavEntry<T>, override val previousEntries: List<NavEntry<T>>, ) : Scene<T> { override val entries: List<NavEntry<T>> = listOf(entry) override val content: @Composable () -> Unit = { entry.Content() } }
  40. data class SinglePaneScene<T : Any>( override val key: Any, val

    entry: NavEntry<T>, override val previousEntries: List<NavEntry<T>>, ) : Scene<T> { override val entries: List<NavEntry<T>> = listOf(entry) override val content: @Composable () -> Unit = { entry.Content() } }
  41. data class SinglePaneScene<T : Any>( override val key: Any, val

    entry: NavEntry<T>, override val previousEntries: List<NavEntry<T>>, ) : Scene<T> { override val entries: List<NavEntry<T>> = listOf(entry) override val content: @Composable () -> Unit = { entry.Content() } }
  42. data class SinglePaneScene<T : Any>( override val key: Any, val

    entry: NavEntry<T>, override val previousEntries: List<NavEntry<T>>, ) : Scene<T> { override val entries: List<NavEntry<T>> = listOf(entry) override val content: @Composable () -> Unit = { entry.Content() } }
  43. Yes Yes Render Scene2 Render Scene1 NavEntries Scene Strategy NavDisplay

    SceneStrategy1 SceneStrategy2 SceneStrategy3 No No Render Scene3 Can create Scene 1 ? Can create Scene 2 ?
  44. Yes Render Scene2 NavEntries Scene Strategy NavDisplay SceneStrategy2 SceneStrategy3 No

    No Render Scene3 Can create Scene 2 ? Yes Render Scene1 SceneStrategy1 Can create Scene 1 ?
  45. Yes Yes Render Scene2 Render Scene1 NavEntries Scene Strategy NavDisplay

    SceneStrategy1 SceneStrategy2 SceneStrategy3 No No Render Scene3 Can create Scene 1 ? Can create Scene 2 ?
  46. public class SinglePaneSceneStrategy<T : Any> : SceneStrategy<T> { override fun

    SceneStrategyScope<T>.calculateScene( entries: List<NavEntry<T>>, ): Scene<T> { return SinglePaneScene( key = entries.last().contentKey, entry = entries.last(), previousEntries = entries.dropLast(1), ) } }
  47. public class SinglePaneSceneStrategy<T : Any> : SceneStrategy<T> { override fun

    SceneStrategyScope<T>.calculateScene( entries: List<NavEntry<T>>, ): Scene<T> { return SinglePaneScene( key = entries.last().contentKey, entry = entries.last(), previousEntries = entries.dropLast(1), ) } }
  48. public class SinglePaneSceneStrategy<T : Any> : SceneStrategy<T> { override fun

    SceneStrategyScope<T>.calculateScene( entries: List<NavEntry<T>>, ): Scene<T> { return SinglePaneScene( key = entries.last().contentKey, entry = entries.last(), previousEntries = entries.dropLast(1), ) } }
  49. public class SinglePaneSceneStrategy<T : Any> : SceneStrategy<T> { override fun

    SceneStrategyScope<T>.calculateScene( entries: List<NavEntry<T>>, ): Scene<T> { return SinglePaneScene( key = entries.last().contentKey, entry = entries.last(), previousEntries = entries.dropLast(1), ) } }
  50. fun <T : Any> rememberTwoPaneSceneStrategy(): TwoPaneSceneStrategy<T> { val windowSizeClass =

    currentWindowAdaptiveInfoV2().windowSizeClass return remember(windowSizeClass) { TwoPaneSceneStrategy(windowSizeClass) } } class TwoPaneSceneStrategy<T : Any>( val windowSizeClass: WindowSizeClass, ) : SceneStrategy<T> { override fun SceneStrategyScope<T>.calculateScene( entries: List<NavEntry<T>>, ): Scene<T>? { if (!windowSizeClass.isWidthAtLeastBreakpoint(LOWER_BOUND)) return null return TwoPaneScene(..) // Now return the Scene. } }
  51. fun <T : Any> rememberTwoPaneSceneStrategy(): TwoPaneSceneStrategy<T> { val windowSizeClass =

    currentWindowAdaptiveInfoV2().windowSizeClass return remember(windowSizeClass) { TwoPaneSceneStrategy(windowSizeClass) } } class TwoPaneSceneStrategy<T : Any>( val windowSizeClass: WindowSizeClass, ) : SceneStrategy<T> { override fun SceneStrategyScope<T>.calculateScene( entries: List<NavEntry<T>>, ): Scene<T>? { if (!windowSizeClass.isWidthAtLeastBreakpoint(LOWER_BOUND)) return null return TwoPaneScene(..) // Now return the Scene. } }
  52. class TwoPaneScene<T : Any>(..) : Scene<T> { //.. companion object

    { fun twoPane() = metadata { put(TwoPaneKey, true) } } } object TwoPaneKey : NavMetadataKey<Boolean>
  53. override fun SceneStrategyScope<T>.calculateScene( entries: List<NavEntry<T>>, ): Scene<T>? { if (!windowSizeClass.isWidthAtLeastBreakpoint(LOWER_BOUND))

    return null val lastTwoEntries = entries.takeLast(2) val optedIn = lastTwoEntries.size == 2 && lastTwoEntries.all { entry -> TwoPaneKey in entry.metadata } if (!optedIn) return null return TwoPaneScene(...) // Now return the Scene. } }
  54. override fun SceneStrategyScope<T>.calculateScene( entries: List<NavEntry<T>>, ): Scene<T>? { if (!windowSizeClass.isWidthAtLeastBreakpoint(LOWER_BOUND))

    return null val lastTwoEntries = entries.takeLast(2) val optedIn = lastTwoEntries.size == 2 && lastTwoEntries.all { entry -> TwoPaneKey in entry.metadata } if (!optedIn) return null return TwoPaneScene(...) // Now return the Scene. } }
  55. class BottomNavSceneDecoratorStrategy<T : Any> : SceneDecoratorStrategy<T> { override fun SceneDecoratorStrategyScope<T>.decorateScene(

    scene: Scene<T>, ): Scene<T> { // If the scene provides metadata for a bottom nav display it. if (scene.metadata.containsKey(NAV_BAR)) { return BottomNavScene(scene) } return scene } }
  56. class BottomNavSceneDecoratorStrategy<T : Any> : SceneDecoratorStrategy<T> { override fun SceneDecoratorStrategyScope<T>.decorateScene(

    scene: Scene<T>, ): Scene<T> { // If the scene provides metadata for a bottom nav display it. if (scene.metadata.containsKey(NAV_BAR)) { return BottomNavScene(scene) } return scene } }
  57. class BottomNavSceneDecoratorStrategy<T : Any> : SceneDecoratorStrategy<T> { override fun SceneDecoratorStrategyScope<T>.decorateScene(

    scene: Scene<T>, ): Scene<T> { // If the scene provides metadata for a bottom nav display it. if (scene.metadata.containsKey(NAV_BAR)) { return BottomNavScene(scene) } return scene } }
  58. class BottomNavSceneDecoratorStrategy<T : Any> : SceneDecoratorStrategy<T> { override fun SceneDecoratorStrategyScope<T>.decorateScene(

    scene: Scene<T>, ): Scene<T> { // If the scene provides metadata for a bottom nav display it. if (scene.metadata.containsKey(NAV_BAR)) { return BottomNavScene(scene) } return scene } } Calls scene.content()
  59. val sceneState = rememberSceneState(..) val navigationEventState = rememberNavigationEventState(sceneState) NavigationBackHandler(sceneState, navigationEventState,

    onBack) NavDisplay( sceneState, navigationEventState, modifier, contentAlignment, sizeTransform, transitionSpec, popTransitionSpec, predictivePopTransitionSpec, )
  60. val sceneState = rememberSceneState(..) val navigationEventState = rememberNavigationEventState(sceneState) NavigationBackHandler(sceneState, navigationEventState,

    onBack) NavDisplay( sceneState, navigationEventState, modifier, contentAlignment, sizeTransform, transitionSpec, popTransitionSpec, predictivePopTransitionSpec, )
  61. val sceneState = rememberSceneState(..) val navigationEventState = rememberNavigationEventState(sceneState) NavigationBackHandler(sceneState, navigationEventState,

    onBack) NavDisplay( sceneState, navigationEventState, modifier, contentAlignment, sizeTransform, transitionSpec, popTransitionSpec, predictivePopTransitionSpec, )
  62. val sceneState = rememberSceneState(..) val navigationEventState = rememberNavigationEventState(sceneState) NavigationBackHandler(sceneState, navigationEventState,

    onBack) NavDisplay( sceneState, navigationEventState, modifier, contentAlignment, sizeTransform, transitionSpec, popTransitionSpec, predictivePopTransitionSpec, )
  63. val sceneState = rememberSceneState(...) val navigationEventState = rememberNavigationEventState(sceneState) NavigationBackHandler(sceneState, navigationEventState,

    onBack) NavDisplay( sceneState, navigationEventState, modifier, contentAlignment, sizeTransform, transitionSpec, popTransitionSpec, predictivePopTransitionSpec, ) True to its name!
  64. AnimatedContent( targetState = sceneState.currentScene, modifier = modifier, transitionSpec = transitionSpec,

    contentAlignment = contentAlignment, contentKey = { scene -> scene.key } ) { targetScene -> targetScene.content() }
  65. AnimatedContent( targetState = sceneState.currentScene, modifier = modifier, transitionSpec = transitionSpec,

    contentAlignment = contentAlignment, contentKey = { scene -> scene.key } ) { targetScene -> targetScene.content() }
  66. val backStack = rememberNavBackStack(config, Home) val entries = rememberDecoratedNavEntries( backStack

    = backStack, entryDecorators = listOf(..), entryProvider = entryProvider {..} ) NavDisplay( entries = entries, onBack = {..} )
  67. val backStack = rememberNavBackStack(config, Home) val entries = rememberDecoratedNavEntries( backStack

    = backStack, entryDecorators = listOf(..), entryProvider = entryProvider {..} ) val sceneState = rememberSceneState(..) val navigationEventState = rememberNavigationEventState(sceneState) NavigationBackHandler(sceneState, navigationEventState, onBackCompleted = {..}) NavDisplay( sceneState, navigationEventState )