我的 Compose Navigation 的层次结构有问题。我使用的 compose-navigation 版本是:
androidx.navigation:navigation-compose:2.7.7
。
我正在尝试使用底部导航和三个选项卡来实现简单的导航。每个选项卡都有自己的嵌套导航,由两个屏幕组成:主选项卡内容和详细信息屏幕,该屏幕在嵌套图表中重复使用。
选项卡 NavHost 的主要活动:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
TestNavigationTheme {
val tabsController = rememberNavController()
Scaffold(
bottomBar = {
NavigationBar {
val navBackStackEntry by tabsController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
BottomTabs.items.forEach { navigationItem ->
NavigationBarItem(
label = { Text(navigationItem.title) },
selected = currentDestination
?.hierarchy
?.any { it.route == navigationItem.route } == true,
icon = { Icon(navigationItem.icon, navigationItem.title) },
onClick = {
tabsController.navigate(navigationItem.route) {
popUpTo(tabsController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
)
}
}
}
) { paddingValues ->
NavHost(
navController = tabsController,
startDestination = BottomTabs.Feed.route,
modifier = Modifier.padding(paddingValues = paddingValues)
) {
navigation(
route = BottomTabs.Feed.route,
startDestination = "feed"
) {
composable(route = "feed") {
FeedScreen {
tabsController.navigate("details/feed")
}
}
details()
}
navigation(
route = BottomTabs.Search.route,
startDestination = "search"
) {
composable(route = "search") {
SearchScreen {
tabsController.navigate("details/search")
}
}
details()
}
navigation(
route = BottomTabs.Favourites.route,
startDestination = "fav"
) {
composable(route = "fav") {
FavouritesScreen {
tabsController.navigate("details/fav")
}
}
details()
}
}
}
}
}
}
private fun NavGraphBuilder.details() {
composable(
route = "details/{argument}",
arguments = listOf(
navArgument("argument") { type = NavType.StringType }
)
) { backStackEntry ->
DetailsScreen(
argument = backStackEntry
.arguments
?.getString("argument")
?: "Couldn't obtain the argument"
)
}
}
}
底部选项卡:
sealed class BottomTabs(val route: String, val title: String, val icon: ImageVector) {
data object Feed : BottomTabs("feed-tab", "Feed", Icons.Default.Home)
data object Search : BottomTabs("search-tab", "Search", Icons.Default.Search)
data object Favourites : BottomTabs("fav-tab", "Favourites", Icons.Default.Favorite)
companion object {
val items = listOf(Feed, Search, Favourites)
}
}
选项卡屏幕:
@Composable
fun FeedScreen(navigateToDetails: () -> Unit) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize()
) {
Text("Hi, I'm Feed screen")
Spacer(modifier = Modifier.size(40.dp))
Button(onClick = navigateToDetails) {
Text(text = "Go to details")
}
}
}
@Composable
fun SearchScreen(navigateToDetails: () -> Unit) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize()
) {
Text("Hi, I'm Search screen")
Spacer(modifier = Modifier.size(40.dp))
Button(onClick = navigateToDetails) {
Text(text = "Go to details")
}
}
}
@Composable
fun FavouritesScreen(navigateToDetails: () -> Unit) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize()
) {
Text("Hi, I'm Favourites screen")
Spacer(modifier = Modifier.size(40.dp))
Button(onClick = navigateToDetails) {
Text(text = "Go to details")
}
}
}
详细信息屏幕:
@Composable
fun DetailsScreen(argument: String) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize()
) {
Text("I'm details screen")
Text("Your argument is: $argument")
}
}
您可以在 NavigationBarItem 中找到此代码,这是我从 Google 导航指南中获取的:
selected = currentDestination
?.hierarchy
?.any { it.route == navigationItem.route } == true
当我切换到第三个选项卡(“最喜欢的选项卡”)并按下按钮打开详细信息屏幕时,详细信息屏幕会在最喜欢的选项卡中正确打开。 但是,导航栏会突出显示所选的提要选项卡,而不是最喜欢的选项卡。
我尝试通过在 NavigationBarItem 中放置断点来调试导航重组周期。这是层次结构:
我不明白为什么
feed-tab
出现为层次结构的根。我认为应该是:
"details/{argument}"
"fav-tab"
因为我从
fav-tab
导航到详细信息屏幕,而不是 feed-tab
。
我在实施过程中做错了什么?任何想法或建议将不胜感激!
问题的原因是详细信息屏幕的路线。所有三个导航图都是一样的。
根据文档,“路线唯一标识目的地及其所需的任何数据。”
因此,我向details() 可组合项添加了前缀,现在一切正常。