Jetpack Compose ModalBottomSheetLayout半屏停留问题解决
ModalBottomSheetLayout 实现无半屏停留的全屏弹窗
问题原因
ModalBottomSheetLayout 组件默认预设三个状态锚点:
Hidden:弹窗完全隐藏HalfExpanded:半屏展开Expanded:全屏展开
下滑关闭时停在半屏,是因为手势滑动过程中组件默认会吸附到HalfExpanded锚点。
修复步骤
1. 配置SheetState拦截半屏状态
初始化rememberModalBottomSheetState时,通过confirmValueChange参数直接拦截半屏状态,禁止组件吸附到该位置:
@OptIn(ExperimentalMaterialApi::class) @Composable fun DetailsScreen() { val coroutineScope = rememberCoroutineScope() val sheetState = rememberModalBottomSheetState( initialValue = ModalBottomSheetValue.Hidden, confirmValueChange = { targetState -> // 拒绝切换到半屏状态 targetState != ModalBottomSheetValue.HalfExpanded } ) // 其余代码逻辑见后续调整 }
2. 修正弹窗内容根布局Modifier
你之前写的wrapContentHeight()会干扰组件高度计算,直接删掉即可,根容器撑满宽高:
ModalBottomSheetLayout( sheetContent = { Box( modifier = Modifier .navigationBarsWithImePadding() .fillMaxSize() .background(Color.White) ) { Column( modifier = Modifier .fillMaxSize() .padding(10.dp) ) { Text( text = "Bottom Sheet", textAlign = TextAlign.Center, style = MaterialTheme.typography.h5, fontWeight = FontWeight.Bold, modifier = Modifier.fillMaxWidth() ) Text( text = "Item 1", style = MaterialTheme.typography.h6, modifier = Modifier.padding(top = 10.dp) ) Text( text = "Item 2", style = MaterialTheme.typography.h6, modifier = Modifier.padding(top = 10.dp) ) Text( text = "Item 3", style = MaterialTheme.typography.h6, modifier = Modifier.padding(top = 10.dp) ) } } }, sheetState = sheetState, sheetBackgroundColor = Color.White ) { Scaffold( topBar = { TopAppBar( title = { Text( text = "Modal Bottom Sheet", modifier = Modifier.fillMaxWidth(), textAlign = TextAlign.Center ) } ) } ) { MainContent( onClick = { coroutineScope.launch { // 直接动画到全屏展开状态,不要用默认show() sheetState.animateTo(ModalBottomSheetValue.Expanded) } }, modifier = Modifier.padding(it) ) } }
3. MainContent组件无需修改
原有MainContent的实现可以直接保留,不需要调整。
@Composable fun MainContent( onClick: () -> Unit, modifier: Modifier = Modifier ) { Box( contentAlignment = Alignment.Center, modifier = modifier.fillMaxSize() ) { Button( onClick = onClick, shape = RoundedCornerShape(10.dp) ) { Text( text = "Click Me!", textAlign = TextAlign.Center, style = MaterialTheme.typography.h6.copy(color = Color.White) ) } } }
最终效果
- 点击按钮后弹窗直接展开至全屏,不会先停在半屏位置

- 下滑关闭弹窗时会直接从全屏过渡到完全隐藏状态,不会在半屏位置停留

- 弹窗全程仅存在「全屏展开」「完全隐藏」两种状态,单次下滑手势即可完成关闭操作。
内容的提问来源于stack exchange,提问作者XCarb
相关产品推荐
相关产品推荐

