You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 05:12:23