
Also available on Medium
Modern Android apps demand seamless, predictable, and maintainable navigation flows. With Navigation 3, Jetpack Compose introduces a more powerful and flexible approach to managing navigation, designed to simplify multiscreen and nested navigation setups.
In this article, I’ll walk you through a simple demo app built to showcase the new Navigation 3 API, its capabilities, and why it’s such a big deal for Compose developers.
⚠️ Note: Navigation 3 is currently in alpha, which means the API may change in future releases. Still, it’s a great time to start experimenting and getting familiar with its new patterns.
🚀 The Demo App Overview
You can find the full demo on GitHub.
Here’s what the app includes:
- Login screen: a simple button that navigates to the main screen.
- Main screen: uses a bottom bar with two items — Tasks and Settings.
- Tasks screen: displays a list of in-memory tasks managed by a
ViewModel. Users can mark tasks as completed and navigate to the details screen with a smooth horizontal slide animation. - Settings screen: for demonstration purposes, it shows how to connect a simple composable to Navigation 3 using a
NavDisplay.
The app uses two NavDisplays:
- One for the Login flow, serving as the root.
- Another for the Main flow, hosting the bottom bar navigation.
🧭 Why Navigation 3 Is a Game Changer
Navigation 3 introduces a cleaner architecture for complex Compose apps, replacing the old boilerplate-heavy setup with a stateful, scalable, and modular navigation model.
Key Benefits
- Simplified nested navigation: handle multiple NavDisplays (like login + bottom bar) without extra scaffolding.
- Type-safe destinations: navigate between screens using well-defined routes.
- Predictable state management: each NavDisplay manages its own state, improving back stack behavior.
- Smooth transitions: built-in support for animation between screens.
It’s a major step forward for developers who want more control and less ceremony in their navigation code.
🧩 A Quick Look at the Code
Here’s an example of how the app handles navigation between the login and main flows:
// Sample Main NavDisplay with a login screen
// This NavDisplay also has the MainScreen entry to replace with the Bottom NavDisplay
@Composable
fun MainNavDisplay() {
val backStack = rememberNavBackStack(AuthenticationRoutes.Login)
NavDisplay(
modifier = Modifier.fillMaxSize(),
backStack = backStack,
entryProvider = entryProvider {
entry<AuthenticationRoutes.Login> {
LoginScreen(
onLoginClick = {
backStack.removeLastOrNull()
backStack.add(MainRoutes.Main)
}
)
}
entry<MainRoutes.Main> {
MainScreenNavEntry()
}
}
)
}
And the MainNavDisplay itself hosts the bottom bar with tasks and settings:
@Composable
fun BottomNavDisplay(
modifier: Modifier = Modifier,
backStack: NavBackStack<NavKey>
) {
NavDisplay(
modifier = modifier.fillMaxSize(),
backStack = backStack,
entryProvider = entryProvider {
entry<TasksRoutes.Task> {
TaskListScreenNavEntry(
onNavigation = {
when(it) {
TaskListNavigation.Back -> backStack.removeLastOrNull()
is TaskListNavigation.Details -> backStack.add(TasksRoutes.Details(it.task))
}
}
)
}
entry<TasksRoutes.Details>(
metadata = slideTransition()
) {
DetailsTaskScreen(
task = it.task,
onBack = {
backStack.removeLastOrNull()
}
)
}
entry<SettingsRoutes.Settings> {
SettingsScreen()
}
}
)
}
📌 Feel free to check out the complete implementation on GitHub and experiment with your own nested navigation setups.
💡 What You’ll Learn from This Demo
- How to use multiple NavDisplays to separate login and main app flows.
- How to navigate between screens with animations and state preservation.
- How to leverage ViewModels in combination with Navigation 3.
- How to scale navigation for more complex applications.
🔧 Try It Yourself
Clone the demo, run it, and tweak the navigation logic.
Experiment with different flows and see how Navigation 3 keeps everything clean and predictable, even with nested graphs and animations.
🧠 Pro Tip: Start integrating Navigation 3 early. Understanding its structure now will give you a big advantage once it reaches beta and stable versions.
🏁 Final Thoughts
Navigation 3 makes Compose development feel more modular, readable, and future-ready.
Even in alpha, it already shows the potential to redefine how we structure app navigation in Android.
If you want to see how it all works in practice, check out the source code on GitHub and follow KMP Bits for more Kotlin and Compose insights.