我正在尝试将Jetpack Compose导航应用到我的应用程序中。
我的屏幕:登录/注册屏幕和底部导航栏屏幕(通话、聊天、设置)。
我已经发现最好的方法是使用嵌套图。
但我一直收到ViewModelStore should be set before setGraph call
异常。然而,我不认为这是正确的例外。
我的导航已经是最新版本了。可能我的嵌套图逻辑不正确。
要求:我希望能够从登录或注册屏幕导航到任何BottomBar屏幕&反向
@Composable
fun SetupNavGraph(
navController: NavHostController,
userViewModel: UserViewModel
) {
NavHost(
navController = navController,
startDestination = BOTTOM_BAR_GRAPH_ROUTE,
route = ROOT_GRAPH_ROUTE
) {
loginNavGraph(navController = navController, userViewModel)
bottomBarNavGraph(navController = navController, userViewModel)
}
}
NavGraph.kt
fun NavGraphBuilder.loginNavGraph(
navController: NavHostController,
userViewModel: UserViewModel
) {
navigation(
startDestination = Screen.LoginScreen.route,
route = LOGIN_GRAPH_ROUTE
) {
composable(
route = Screen.LoginScreen.route,
content = {
LoginScreen(
navController = navController,
loginViewModel = userViewModel
)
})
composable(
route = Screen.RegisterScreen.route,
content = {
RegisterScreen(
navController = navController,
loginViewModel = userViewModel
)
})
}
}
LoginNavGraph.kt
fun NavGraphBuilder.bottomBarNavGraph(
navController: NavHostController,
userViewModel: UserViewModel
) {
navigation(
startDestination = Screen.AppScaffold.route,
route = BOTTOM_BAR_GRAPH_ROUTE
) {
composable(
route = Screen.AppScaffold.route,
content = {
AppScaffold(
navController = navController,
userViewModel = userViewModel
)
})
}
}
BottomBarNavGraph.kt
@Composable
fun AppScaffold(
navController: NavHostController,
userViewModel: UserViewModel
) {
val scaffoldState = rememberScaffoldState()
Scaffold(
bottomBar = {
BottomBar(mainNavController = navController)
},
scaffoldState = scaffoldState,
) {
NavHost(
navController = navController,
startDestination = NavigationScreen.EmergencyCallScreen.route
) {
composable(NavigationScreen.EmergencyCallScreen.route) {
EmergencyCallScreen(
navController = navController,
loginViewModel = userViewModel
)
}
composable(NavigationScreen.ChatScreen.route) { ChatScreen() }
composable(NavigationScreen.SettingsScreen.route) {
SettingsScreen(
navController = navController,
loginViewModel = userViewModel
)
}
}
}
}
AppScaffold.kt
@Composable
fun BottomBar(mainNavController: NavHostController) {
val items = listOf(
NavigationScreen.EmergencyCallScreen,
NavigationScreen.ChatScreen,
NavigationScreen.SettingsScreen,
)
BottomNavigation(
elevation = 5.dp,
) {
val navBackStackEntry by mainNavController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
items.map {
BottomNavigationItem(
icon = {
Icon(
painter = painterResource(id = it.icon),
contentDescription = it.title
)
},
label = {
Text(
text = it.title
)
},
selected = currentRoute == it.route,
selectedContentColor = Color.White,
unselectedContentColor = Color.White.copy(alpha = 0.4f),
onClick = {
mainNavController.navigate(it.route) {
mainNavController.graph.startDestinationRoute?.let { route ->
popUpTo(route) {
saveState = true
}
}
restoreState = true
launchSingleTop = true
}
},
)
}
}
}
BottomBar.kt
const val ROOT_GRAPH_ROUTE = "root"
const val LOGIN_GRAPH_ROUTE = "login_register"
const val BOTTOM_BAR_GRAPH_ROUTE = "bottom_bar"
sealed class Screen(val route: String) {
object LoginScreen : Screen("login_screen")
object RegisterScreen : Screen("register_screen")
object AppScaffold : Screen("app_scaffold")
}
Screen.kt
sealed class NavigationScreen(val route: String, val title: String, @DrawableRes val icon: Int) {
object EmergencyCallScreen : NavigationScreen(
route = "emergency_call_screen",
title = "Emergency Call",
icon = R.drawable.ic_phone
)
object ChatScreen :
NavigationScreen(
route = "chat_screen",
title = "Chat",
icon = R.drawable.ic_chat)
object SettingsScreen : NavigationScreen(
route = "settings_screen",
title = "Settings",
icon = R.drawable.ic_settings
)
}
NavigationScreen.kt
发布于 2021-11-13 16:14:06
不允许嵌套NavHost。这会导致在setGraph调用异常之前设置ViewModelStore。通常,docs显示的底部nav在NavHost之外。推荐的方法是一个单一的NavHost,你可以根据你所在的目的地隐藏和显示你的底部导航。
https://stackoverflow.com/questions/69738397
复制相似问题