I don't think my code is compact. Do I always have to hand over the Nav Controller to the argument in this way?
@Composable
fun ChatHome(
navController: NavController,
appViewModel: AppViewModel
) {
ChatList(navController)
}
@Composable
fun ChatList(navController: NavController) {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 16.dp, vertical = 8.dp)
) {
items(chatItemList) { chat ->
ChatItem(chat, navController) {}
}
}
}
@Composable
fun ChatItem(
chat: Chat,
navController: NavController,
onRowClick: (Chat) -> Unit
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(10.dp)
.clickable(onClick = {
onRowClick(chat)
navController.navigate("chatDetail/${chat.chatId}")
})
)
...
I wonder how to use Nav Controller globally.
Note: If you wan't preview-able composable, you can write own wrapper:
// For single component
@Composable
fun ComposablePreview(content: @Composable () -> Unit) {
CompositionLocalProvider(
LocalNavigation provides rememberNavController(),
content = content,
)
}
// For theme
@Composable
fun AppThemePreview(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit,
) {
CompositionLocalProvider(
LocalNavigation provides rememberNavController()
) {
AppTheme(darkTheme, content)
}
}
// Usage
@Preview
@Composable
fun ComponentPreview() {
ComposablePreview {
// Some composable
}
}
@Preview
@Composable
fun ComponentPreviewWithTheme() {
AppThemePreview {
// Some composable
}
}
Original answer:
You can use CompositionLocalProvider.
For example:
Define our CompositionLocal
with NavHostController
val LocalNavigation = staticCompositionLocalOf<NavHostController> { error("Not provided") }
Wrap your whole project with CompositionLocalProvider
val navController = rememberNavController()
CompositionLocalProvider(
LocalNavigation provides navController,
) {
NavHost(navController = navController, ...) { ... }
}
And now you can call it like that:
@Composable
fun ChatItem(
chat: Chat,
onRowClick: (Chat) -> Unit
) {
val navController = LocalNavigation.current
Row(
modifier = Modifier
.fillMaxWidth()
.padding(10.dp)
.clickable(onClick = {
onRowClick(chat)
navController.navigate("chatDetail/${chat.chatId}")
})
)
}