NavOptionsBuilder.launchSingleTop 是否适用于 Jetpack Compose 中的嵌套导航图?
Does NavOptionsBuilder.launchSingleTop work with nested navigation graphs in Jetpack Compose?
我在 Jetpack Compose 中使用 BottomNavigation
和 navigation-compose:2.5.0-alpha04
,我想用 nested navigation 封装每个选项卡的流程。为此,我创建了一个包含不同图形的 NavHost:
NavHost(
navController = navController,
startDestination = defaultTab.route
) {
eventsGraph()
employeesGraph()
devicesGraph()
feedbackGraph()
}
每个图在 navigation
扩展函数中包含自己的 composable
。
正如 docs 所建议的那样,当 BottomNavigationItem
被点击时,我正在按以下方式配置我的 NavOptions
:
onClick = {
navController.navigate(tab.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
// We want to reset the graph if it is clicked while already selected
restoreState = tab != currentTab
}
currentTab = tab
}
我希望此代码忽略对已选定项目的点击,并始终将任何选定的选项卡作为导航图的根,即如果用户位于任何给定选项卡的根目的地,则在返回时退出应用程序。
相反,在其起始目的地的默认选项卡上的每次单击都会将同一目的地的另一个实例放入堆栈中,而在非默认选项卡上按回键会使我回到 defaultTab
的目的地.
我尝试弹出目的地 inclusive
,但 NavController
不出所料,就是找不到已保存的 Destination
的 ID 来恢复状态。我尝试 saveState
恢复它的相同 tab != currentTab
条件,但它似乎没有效果。
是否可以通过导航 API 实现所需的行为,还是我需要自己处理?
更新
我最终想出了以下重置当前选项卡图表的解决方案。基本上,我们不是使用 popUpTo
选项导航,而是将堆栈弹出到起始目的地。
onClick = {
if (tab == currentTab) {
navController.popBackStack(
route = tab.startDestination,
inclusive = false
)
return@BottomNavigationItem
}
/* ... */
}
defaultTab
的图形作为根仍然存在问题,这意味着在任何非默认选项卡的启动时按下后退按钮不会退出应用程序。
简答:是的,你需要自己写这个逻辑。幸运的是,大部分由导航库处理。
要求:
- 堆栈中一次一个选项卡
- 选项卡的导航状态在离开时保存并在进入时恢复
- 所选选项卡的导航状态在点击时重置
- 任何选定的选项卡都是导航图的根
除 4 项外,其余均已达成。由于 ianhanniballake ,按系统后退键退出应用程序必须始终发生在应用程序的启动目的地,因此我保留了默认行为。
至于第 1-3 项,这里是 BottomNavigationItem
的完整 onClick
实施:
onClick = {
// Handling resetting current tab's state
if (tab == currentTab) {
navController.popBackStack(
route = tab.startDestination,
inclusive = false
)
return@BottomNavigationItem
}
// Handling singleTop behavior with saving state
navController.navigate(tab.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = tab != currentTab
}
appBarViewModel.setCurrentTab(tab)
}
这有什么棘手的是,当按系统后退后显示 defaultTab
时,以前实现的 currentTab
不会更新,所以我正在根据当前导航返回堆栈作为侧面更新它效果:
val navBackStackEntry by navController.currentBackStackEntryAsState()
LaunchedEffect(navBackStackEntry) {
// This condition is possible to be true if a system "Back" press was detected in a non-default tab,
// navigating the user to app's start destination.
// To correctly reflect that in bottom navigation, this code is needed
if (navBackStackEntry?.destination?.route == appBarViewModel.defaultTab.startDestination)
appBarViewModel.setCurrentTab(appBarViewModel.defaultTab)
}
我在 Jetpack Compose 中使用 BottomNavigation
和 navigation-compose:2.5.0-alpha04
,我想用 nested navigation 封装每个选项卡的流程。为此,我创建了一个包含不同图形的 NavHost:
NavHost(
navController = navController,
startDestination = defaultTab.route
) {
eventsGraph()
employeesGraph()
devicesGraph()
feedbackGraph()
}
每个图在 navigation
扩展函数中包含自己的 composable
。
正如 docs 所建议的那样,当 BottomNavigationItem
被点击时,我正在按以下方式配置我的 NavOptions
:
onClick = {
navController.navigate(tab.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
// We want to reset the graph if it is clicked while already selected
restoreState = tab != currentTab
}
currentTab = tab
}
我希望此代码忽略对已选定项目的点击,并始终将任何选定的选项卡作为导航图的根,即如果用户位于任何给定选项卡的根目的地,则在返回时退出应用程序。
相反,在其起始目的地的默认选项卡上的每次单击都会将同一目的地的另一个实例放入堆栈中,而在非默认选项卡上按回键会使我回到 defaultTab
的目的地.
我尝试弹出目的地 inclusive
,但 NavController
不出所料,就是找不到已保存的 Destination
的 ID 来恢复状态。我尝试 saveState
恢复它的相同 tab != currentTab
条件,但它似乎没有效果。
是否可以通过导航 API 实现所需的行为,还是我需要自己处理?
更新
我最终想出了以下重置当前选项卡图表的解决方案。基本上,我们不是使用 popUpTo
选项导航,而是将堆栈弹出到起始目的地。
onClick = {
if (tab == currentTab) {
navController.popBackStack(
route = tab.startDestination,
inclusive = false
)
return@BottomNavigationItem
}
/* ... */
}
defaultTab
的图形作为根仍然存在问题,这意味着在任何非默认选项卡的启动时按下后退按钮不会退出应用程序。
简答:是的,你需要自己写这个逻辑。幸运的是,大部分由导航库处理。
要求:
- 堆栈中一次一个选项卡
- 选项卡的导航状态在离开时保存并在进入时恢复
- 所选选项卡的导航状态在点击时重置
- 任何选定的选项卡都是导航图的根
除 4 项外,其余均已达成。由于 ianhanniballake
至于第 1-3 项,这里是 BottomNavigationItem
的完整 onClick
实施:
onClick = {
// Handling resetting current tab's state
if (tab == currentTab) {
navController.popBackStack(
route = tab.startDestination,
inclusive = false
)
return@BottomNavigationItem
}
// Handling singleTop behavior with saving state
navController.navigate(tab.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = tab != currentTab
}
appBarViewModel.setCurrentTab(tab)
}
这有什么棘手的是,当按系统后退后显示 defaultTab
时,以前实现的 currentTab
不会更新,所以我正在根据当前导航返回堆栈作为侧面更新它效果:
val navBackStackEntry by navController.currentBackStackEntryAsState()
LaunchedEffect(navBackStackEntry) {
// This condition is possible to be true if a system "Back" press was detected in a non-default tab,
// navigating the user to app's start destination.
// To correctly reflect that in bottom navigation, this code is needed
if (navBackStackEntry?.destination?.route == appBarViewModel.defaultTab.startDestination)
appBarViewModel.setCurrentTab(appBarViewModel.defaultTab)
}