【问题标题】:How can Jetpack Compose Navigation remember multiple back stacks?Jetpack Compose Navigation 如何记住多个返回堆栈?
【发布时间】:2023-02-21 05:59:21
【问题描述】:

我正在阅读 Jetpack Compose 中的导航,发现这个例子我不明白。

来自the docs

通过使用 saveStaterestoreState 标志,状态和返回堆栈当您在底部导航项目之间切换时,该项目的部分已正确保存和恢复。

val navController = rememberNavController()
Scaffold(
  bottomBar = {
    BottomNavigation {
      val navBackStackEntry by navController.currentBackStackEntryAsState()
      val currentDestination = navBackStackEntry?.destination
      items.forEach { screen ->
        BottomNavigationItem(
          icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
          label = { Text(stringResource(screen.resourceId)) },
          selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
          onClick = {
            navController.navigate(screen.route) {
              // Pop up to the start destination of the graph to
              // avoid building up a large stack of destinations
              // on the back stack as users select items
              popUpTo(navController.graph.findStartDestination().id) {
                saveState = true
              }
              // Avoid multiple copies of the same destination when
              // reselecting the same item
              launchSingleTop = true
              // Restore state when reselecting a previously selected item
              restoreState = true
            }
          }
        )
      }
    }
  }
) { innerPadding ->
  NavHost(navController, startDestination = Screen.Profile.route, Modifier.padding(innerPadding)) {
    composable(Screen.Profile.route) { Profile(navController) }
    composable(Screen.FriendsList.route) { FriendsList(navController) }
  }
}

具体来说,我不明白如果单击底部栏中的项目弹出导航堆栈,如何保存返回堆栈to the root

我会想象这样的旅程:

  1. 用户移动到/FriendsList/Friend(A)/Friend(B)/Friend(C)
  2. 用户单击Profile按钮,将导航堆栈重置为/Profile
  3. 用户点击FriendsList按钮。

    根据解释,我希望导航堆栈重新设置为/FriendsList/FriendA/FriendB/FriendC,即使onClick 侦听器似乎将堆栈设置为/FriendsList

    我真的不明白这是怎么发生的,导航控制器如何将路由链接到整个导航子堆栈? item.route 是否正在更改包含到 /FriendsList/Friend(A)/Friend(B)/Friend(C) 的完整路由的状态,或者是否发生了其他事情?还是我理解错了这个例子?

    我怀疑潜在的机制可能是 FriendsList 包含嵌套导航图,因为该示例实际上并未显示任何 Friend 路由定义。整个嵌套图的状态以某种方式包含,即类似/FriendsList{FriendA/FriendB/FriendC} 的状态,移动到/FriendsList 将解压此导航堆栈。它是这样运作的吗?

【问题讨论】:

    标签: jetpack-compose-navigation


    【解决方案1】:

    我知道我的回答有点晚了,但这些天我一直在寻找具有相同行为的解决方案,最终我找到了一个。 要实现此行为,您需要声明嵌套的 navHosts。他们每个人都有自己的 navController,仅此而已。所有其余的都是自动工作的。

    这是一个例子

    val navController = rememberNavController()
    val navBackStackEntry by navController.currentBackStackEntryAsState()
    val currentDestination = navBackStackEntry?.destination
    
    Scaffold(
        bottomBar = {
            BottomNavigation {
                items.forEach { screen ->
                    BottomNavigationItem(
                        icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
                        label = { Text(stringResource(screen.resourceId)) },
                        selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
                        onClick = {
                            navController.navigate(screen.route) {
                                // Pop up to the start destination of the graph to
                                // avoid building up a large stack of destinations
                                // on the back stack as users select items
                                popUpTo(navController.graph.findStartDestination().id) {
                                    saveState = true
                                }
                                // Avoid multiple copies of the same destination when
                                // reselecting the same item
                                launchSingleTop = true
                                // Restore state when reselecting a previously selected item
                                restoreState = true
                            }
                        }
                    )
                }
            }
        }
    ) { innerPadding ->
    
        NavHost(
            navController,
            startDestination = Screen.ProfileNavHost.route,
            Modifier.padding(innerPadding)
        ) {
    
            composable(Screen.ProfileNavHost.route) {
                val profileNavController = rememberNavController()
                NavHost(
                    navController = profileNavController,
                    startDestination = Screen.ProfileRoot.route
                ) {
                    composable(Screen.ProfileRoot.route) {
                        ProfileRoot(navController)
                    }
                    composable(Screen.ProfileScreen.route) {
                        ProfileScreen(navController)
                    }
                }
            }
    
            composable(Screen.FriendsListNavHost.route) {
                val friendsListNavController = rememberNavController()
                NavHost(
                    navController = friendsListNavController,
                    startDestination = Screen.FriendsListRoot.route
                ) {
                    composable(Screen.FriendsListRoot.route) {
                        FriendsList(navController)
                    }
                    composable(Screen.FriendsListFriend.route) {
                        FriendsListFriend(navController)
                    }
                }
            }
        }
    }
    

    在上面的示例中,您还可以为配置文件选项卡设置一个后退堆栈,如果您不需要它,您可以从可组合项 (Screen.ProfileNavHost.route) 中删除 navHost 和 navController,然后调用您的 Screen 可组合项。

    【讨论】:

      猜你喜欢
      • 2021-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多