Navigation
To use the Navigator you should first import cafe.adriel.voyager:voyager-navigator (see Setup).

Screen

On Voyager, screens are just classes with a composable function as the entrypoint. To create one, you should implement the Screen interface and override the Content() composable function.
You can use data class (if you need to send params), class (if no param is required) or even object (useful for tabs).
1
object HomeScreen : Screen {
2
3
@Composable
4
override fun Content() {
5
// ...
6
}
7
}
8
9
class PostListScreen : Screen {
10
11
@Composable
12
override fun Content() {
13
// ...
14
}
15
}
16
17
data class PostDetailsScreen(val postId: Long) : Screen {
18
19
@Composable
20
override fun Content() {
21
// ...
22
}
23
}
Copied!
Navigator is a composable function deeply integrated with Compose internals. It'll manage the lifecyle, back press, state restoration and even nested navigation for you.
To start using it, just set the initial Screen.
1
class SingleActivity : ComponentActivity() {
2
3
override fun onCreate(savedInstanceState: Bundle?) {
4
super.onCreate(savedInstanceState)
5
6
setContent {
7
Navigator(HomeScreen)
8
}
9
}
10
}
Copied!
Use the LocalNavigator to navigate to other screens. Take a look at the Stack API for the available operations.
1
class PostListScreen : Screen {
2
3
@Composable
4
override fun Content() {
5
// ...
6
}
7
8
@Composable
9
private fun PostCard(post: Post) {
10
val navigator = LocalNavigator.currentOrThrow
11
12
Card(
13
modifier = Modifier.clickable {
14
navigator.push(PostDetailsScreen(post.id))
15
// Also works:
16
// navigator push PostDetailsScreen(post.id)
17
// navigator += PostDetailsScreen(post.id)
18
}
19
) {
20
// ...
21
}
22
}
23
}
Copied!
If part of your UI is shared between screens, like the TopAppBar or BottomNavigation, you can easily reuse them with Voyager.
1
@Composable
2
override fun Content() {
3
Navigator(HomeScreen) { navigator ->
4
Scaffold(
5
topBar = { /* ... */ },
6
content = { CurrentScreen() },
7
bottomBar = { /* ... */ }
8
)
9
}
10
}
Copied!
You should use CurrentScreen() instead of navigator.lastItem.Content(), because it will save the Screen's subtree for you (see SaveableStateHolder).

Sample

Source code here.
Copy link