滑动关闭ModalBottomSheet后底层布局无法交互的问题及解决记录
更新于2023年10月12日
我文中提到的问题已解决。我通过MVVM模式重构了应用结构,分离后端逻辑与前端UI代码。该问题可能与应用结构混乱有关,但暂无法明确原因,故保留此帖等待他人解答。
原帖内容
背景
我正遵循官方文档在应用中创建ModalBottomSheet,但发现滑动关闭该组件后,其后方的布局虽视觉上已无遮挡,却无法进行交互,需按下设备物理或虚拟返回键才能恢复交互。
我的代码
... var openBottomSheet by mutableStateOf(false) @OptIn(ExperimentalMaterial3Api::class) lateinit var bottomSheetState: SheetState @Composable fun GradeScreen( gradeViewModel: GradeViewModel ) { ... val scope = rememberCoroutineScope() bottomSheetState = rememberModalBottomSheetState( skipPartiallyExpanded = true ) // My debug Log.d("bottomSheetState", bottomSheetState.currentValue.toString()) Log.d("bottomSheetState", bottomSheetState.targetValue.toString()) Log.d("bottomSheetState", bottomSheetState.isVisible.toString()) Log.d("bottomSheetState", openBottomSheet.toString()) Log.d("bottomSheetState", "------------------------------------") // Main content ... // Sheet content if (openBottomSheet) { ModalBottomSheet( onDismissRequest = { openBottomSheet = false }, sheetState = bottomSheetState, ) { Column( modifier = Modifier .fillMaxWidth() .padding(15.dp), verticalArrangement = Arrangement.spacedBy(10.dp), ) { // Main content ... // Close button FloatingActionButton( // Note: If you provide logic outside of onDismissRequest to remove the sheet, // you must additionally handle intended state cleanup, if any. onClick = { scope.launch { bottomSheetState.hide() }.invokeOnCompletion { if (!bottomSheetState.isVisible) { openBottomSheet = false } } ... }, modifier = Modifier.align(Alignment.End) ) { Icon( imageVector = Icons.Outlined.Check, contentDescription = null, ) } } } } } @OptIn(ExperimentalMaterial3Api::class) @Composable fun CreateTopBarActionsForGrade() { IconButton( onClick = { openBottomSheet = true } ) { Icon( imageVector = rememberFilterAlt(), contentDescription = null, ) } }
排查发现
经调试发现,问题根源在于滑动关闭ModalBottomSheet时,openBottomSheet的值并未改为false。而点击外部或关闭按钮能成功修改该值,是因为我针对这两种场景编写了对应代码。
解决方案建议
- 监听SheetState状态变化:用
LaunchedEffect监听bottomSheetState.currentValue,当状态变为Hidden时自动更新openBottomSheetLaunchedEffect(bottomSheetState.currentValue) { if (bottomSheetState.currentValue == SheetValue.Hidden) { openBottomSheet = false } } - 统一关闭逻辑:封装关闭函数,让滑动、点击外部、按钮关闭都调用同一逻辑
然后修改// 在GradeScreen内定义 val closeBottomSheet = { scope.launch { bottomSheetState.hide() }.invokeOnCompletion { if (!bottomSheetState.isVisible) { openBottomSheet = false } } }ModalBottomSheet的onDismissRequest:onDismissRequest = { closeBottomSheet() } - 修正SheetState声明方式:将
bottomSheetState移到GradeScreen内部,用remember管理,避免全局lateinit导致的状态异常@Composable fun GradeScreen( gradeViewModel: GradeViewModel ) { val scope = rememberCoroutineScope() val bottomSheetState = rememberModalBottomSheetState( skipPartiallyExpanded = true ) var openBottomSheet by remember { mutableStateOf(false) } // 后续逻辑保持不变 }
内容的提问来源于stack exchange,提问作者jayfunc
相关产品推荐
相关产品推荐

