Skip to content

Navigation 3

Navigation 3 is a new navigation library designed to work with Compose. With Navigation 3, you have full control over your back stack, and navigating to and from destinations is as simple as adding and removing items from a list.

// In libs.versions.toml
[versions]
nav3 = "1.1.0-alpha02"
[libraries]
androidx-navigation3-runtime = { module = "androidx.navigation3:navigation3-runtime", version.ref = "nav3" }
androidx-navigation3-ui = { module = "androidx.navigation3:navigation3-ui", version.ref = "nav3" }
// In build.gradle.kts
dependencies {
implementation("androidx.navigation3:navigation3-runtime:1.1.0-alpha02")
implementation("androidx.navigation3:navigation3-ui:1.1.0-alpha02")
}

You own the back stack: You, the developer, not the library, own and control the back stack. It’s a simple list which is backed by Compose state. Specifically, Nav3 expects your back stack to be SnapshotStateList<T> where T can be any type you choose. You can navigate by adding or removing items, and state changes are observed and reflected by Nav3’s UI.

Routes must implement NavKey and be @Serializable:

@Serializable
data object Home : NavKey
@Serializable
data object Profile : NavKey
@Serializable
data class Detail(val id: String) : NavKey
@Composable
fun MainNavDisplay() {
val backStack = rememberNavBackStack(Home)
NavDisplay(
modifier = Modifier.fillMaxSize(),
backStack = backStack,
entryProvider = entryProvider {
entry<Home> {
HomeScreen(
onNavigateToProfile = { backStack.add(Profile) }
)
}
entry<Profile> {
ProfileScreen(
onBack = { backStack.removeLastOrNull() }
)
}
entry<Detail> { key ->
DetailScreen(id = key.id)
}
}
)
}
// Navigate forward
backStack.add(Profile)
// Navigate back
backStack.removeLastOrNull()
// Replace current
backStack.removeLastOrNull()
backStack.add(NewScreen)
// Clear and navigate
backStack.clear()
backStack.add(Home)

The rememberNavBackStack composable function is designed to create a back stack that persists across configuration changes and process death.

val backStack = rememberNavBackStack(Home)

Requirements for keys:

  • Implement NavKey interface
  • Have @Serializable annotation

Nav3 introduces the concept of Scene and SceneStrategy, enabling the display of multiple destinations simultaneously. This is particularly useful for creating responsive UIs that adapt to different screen sizes.

// Example: List-Detail layout
NavDisplay(
backStack = backStack,
sceneStrategy = ListDetailSceneStrategy(),
entryProvider = entryProvider {
entry<List> { ListScreen() }
entry<Detail> { DetailScreen() }
}
)

Built-in transition animations are provided. Override at app or screen level:

entry<Profile>(
transitions = NavTransitions(
enter = slideInHorizontally { it },
exit = slideOutHorizontally { -it }
)
) {
ProfileScreen()
}

Example with login flow and bottom bar:

@Composable
fun RootNavDisplay() {
val backStack = rememberNavBackStack(LoginRoute)
NavDisplay(
backStack = backStack,
entryProvider = entryProvider {
entry<LoginRoute> {
LoginScreen(
onLoginSuccess = {
backStack.removeLastOrNull()
backStack.add(MainRoute)
}
)
}
entry<MainRoute> {
MainScreenWithBottomBar()
}
}
)
}
@Composable
fun MainScreenWithBottomBar() {
val bottomBackStack = rememberNavBackStack(TasksRoute)
Scaffold(
bottomBar = { /* Bottom navigation */ }
) {
NavDisplay(
backStack = bottomBackStack,
entryProvider = entryProvider {
entry<TasksRoute> { TasksScreen() }
entry<SettingsRoute> { SettingsScreen() }
}
)
}
}
Nav3Nav2
Developer owns back stackLibrary owns back stack
SnapshotStateList<T>NavController
NavDisplayNavHost
Type-safe Kotlin routesString routes or Safe Args
Built for ComposeOriginally for Fragments