Jetpack 撰写导航:为什么我的目的地层次结构错误?

问题描述 投票:0回答:1

问题:

我的 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 中放置断点来调试导航重组周期。这是层次结构:

enter image description here

我不明白为什么

feed-tab
出现为层次结构的根。我认为应该是:

"details/{argument}"
"fav-tab"

因为我从

fav-tab
导航到详细信息屏幕,而不是
feed-tab

我在实施过程中做错了什么?任何想法或建议将不胜感激!

android android-jetpack-compose android-jetpack jetpack-compose-navigation
1个回答
0
投票

问题的原因是详细信息屏幕的路线。所有三个导航图都是一样的。

根据文档,“路线唯一标识目的地及其所需的任何数据。”

因此,我向details() 可组合项添加了前缀,现在一切正常。

© www.soinside.com 2019 - 2024. All rights reserved.