向前导航时如何将Bottom Sheet保留在返回栈中
项目中使用Accompanist Bottom Sheet Destinations实现底部弹窗导航,参考官方示例编写实现代码如下:
@Composable fun MyApp() { val bottomSheetNavigator = rememberBottomSheetNavigator() val navController = rememberNavController(bottomSheetNavigator) ModalBottomSheetLayout(bottomSheetNavigator) { NavHost(navController, Destinations.Home) { composable(route = "home") { HomeScreen( openBottomSheet = { navController.navigate("sheet") } ) } bottomSheet(route = "sheet") { MyBottonSheet( navigateToSomeRoute = { navController.navigate("some_route") } ) } composable(route = "some_route") { SomeComposable( onBackPress = { navController.navigateUp() } ) } } } }
在MyBottomSheet中点击按钮跳转至SomeComposable页面后,调用navigateUp()返回时会直接回到HomeScreen,底部弹窗在导航离开时被自动移出返回栈,无法实现返回后保留MyBottomSheet打开状态的效果。
BottomSheetNavigator默认开启了dismissOnDestinationChanged配置,当导航到任意非底部弹窗类型的目的地时,会自动将当前打开的底部弹窗从返回栈中弹出、关闭弹窗,因此返回时会直接跳过弹窗回到上一个全屏页面。
基础配置(满足绝大多数场景)
修改rememberBottomSheetNavigator的初始化参数,关闭目的地变化时自动关闭弹窗的默认行为:
val bottomSheetNavigator = rememberBottomSheetNavigator( dismissOnDestinationChanged = false // 核心配置 )
修改后返回栈会严格按照导航顺序保留所有目的地,交互逻辑完全符合预期:
- 初始进入首页:返回栈为
[home] - 打开底部弹窗:返回栈为
[home, sheet],弹窗正常显示 - 从弹窗跳转到
some_route:返回栈为[home, sheet, some_route],弹窗不会被自动关闭,仅被上层的SomeComposable页面遮挡 - 在
SomeComposable触发返回:some_route被弹出,返回栈回到[home, sheet],底部弹窗保持原有打开状态叠加在首页之上 - 再次触发返回:弹窗关闭,
sheet被弹出,回到首页
注意:
dismissOnDestinationChanged参数在accompanist-navigation-material 0.24.0及以上版本提供,若使用更低版本请先升级依赖。
小提示:如果在弹窗打开时需要执行跳转并关闭弹窗(比如切换底部Tab、跳转登录页等场景),在导航前手动调用bottomSheetNavigator.dismiss()即可主动关闭弹窗。
进阶场景:按需控制弹窗是否保留
如果不需要全局保留弹窗,仅在跳转特定页面时保留弹窗状态,可以保持dismissOnDestinationChanged默认的true值,在需要保留弹窗的跳转逻辑中手动持有当前弹窗状态,导航返回时手动恢复弹窗显示。该方案实现复杂度较高,非必要场景优先使用全局配置方案即可。
内容的提问来源于stack exchange,提问作者Arpit Shukla

