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

BottomSheetScaffold半展开(HalfExpanded)状态异常问题求助

解决BottomSheetScaffold半展开交互与高度异常问题

问题根源

你当前的实现错误地将sheetPeekHeight与底部弹窗的状态高度绑定,通过confirmValueChange动态修改sheetHeight会触发组件重复重组,导致状态循环冲突,出现卡顿、无法正常隐藏的问题。另外,sheetPeekHeight的作用是控制底部弹窗默认"露出"的高度,并非半展开状态的高度,直接依赖它设置半展开高度属于逻辑错误。

解决方案

  1. 直接指定半展开高度:在rememberStandardBottomSheetState中通过partiallyExpandedHeight参数设置半展开时的高度,无需动态修改sheetPeekHeight。
  2. 解除状态绑定:移除confirmValueChange中修改sheetHeight的逻辑,避免状态循环触发重组。
  3. 开启交互支持:确保底部弹窗在半展开状态时,屏幕其他区域可交互,保证内容区域的触摸事件能正常传递,按需设置手势开关。

修正后的代码

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Screen() {
    val configuration = LocalConfiguration.current
    val screenHeight = configuration.screenHeightDp.dp
    // 直接定义半展开高度为屏幕一半
    val halfScreenHeight = screenHeight / 2

    val sheetState = rememberStandardBottomSheetState(
        initialValue = SheetValue.Hidden,
        // 指定半展开状态的高度
        partiallyExpandedHeight = halfScreenHeight,
        skipHiddenState = false,
        confirmValueChange = {
            // 仅做状态变更确认,无需修改sheetHeight
            true
        }
    )

    val scaffoldState = rememberBottomSheetScaffoldState(bottomSheetState = sheetState)
    val coroutineScope = rememberCoroutineScope()

    BottomSheetScaffold(
        scaffoldState = scaffoldState,
        // 默认不露出弹窗,需固定露出高度可自行设置
        sheetPeekHeight = 0.dp,
        // 允许手势操作,不阻塞内容区域交互
        sheetGesturesEnabled = true,
        sheetContent = {
            Box(
                modifier = Modifier
                    .height(halfScreenHeight)
                    .background(Color.LightGray)
            ) {
                Text(text = "半展开弹窗内容", modifier = Modifier.align(Alignment.Center))
            }
        }
    ) { innerPadding ->
        Button(
            modifier = Modifier
                .height(50.dp)
                .padding(innerPadding),
            onClick = {
                coroutineScope.launch {
                    when(sheetState.currentValue) {
                        SheetValue.PartiallyExpanded -> sheetState.hide()
                        else -> sheetState.partialExpand()
                    }
                }
            },
        ) {
            Text(text = if (sheetState.currentValue == SheetValue.PartiallyExpanded) "隐藏弹窗" else "半展开弹窗")
        }

        // 验证半展开时其他区域可交互的示例组件
        Text(
            text = "屏幕其他区域的可交互内容",
            modifier = Modifier
                .padding(top = 100.dp, start = 16.dp)
                .clickable {
                    println("点击了屏幕其他区域")
                }
        )
    }
}

关键说明

  • partiallyExpandedHeight:这是控制半展开高度的正确参数,直接定义半展开状态下的弹窗高度,无需依赖sheetPeekHeight。
  • sheetPeekHeight:设为0表示默认完全隐藏弹窗,若需要默认露出一部分可设置固定值,不要动态绑定状态。
  • 内容区域交互:通过innerPadding避免内容被弹窗遮挡,添加clickable等修饰符即可实现半展开时的正常交互,若需点击外部关闭弹窗,可在内容区域添加全局点击事件处理。

内容的提问来源于stack exchange,提问作者memeprincess

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 22:49:58