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

如何实现ModalBottomSheetLayout弹出时背景变暗且不可点击?

ModalBottomSheetLayout 弹窗背景变暗且不可点击的实现方案

问题场景

使用ModalBottomSheetLayout时,需要实现:底部弹窗打开时,背景区域变暗且无法点击。但遇到以下问题:

  • 设置screenColor为Color.Unspecified时,背景不可点击但无变暗效果;
  • 手动添加背景遮罩实现变暗后,背景区域变为可点击,底层控件会被误触发。

解决方案

无需手动添加遮罩层,直接利用ModalBottomSheetLayout自带的scrimColor属性即可同时实现背景变暗和不可点击的需求:

  1. 移除代码中手动添加的遮罩Box;
  2. 在ModalBottomSheetLayout中配置scrimColor参数,根据弹窗状态动态设置半透明黑色;
  3. 移除冗余的bottomSheetOpen状态,直接通过bottomSheetState的状态判断弹窗是否显示。

修改后的完整代码

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun ForpostScreen(forpostViewModel: ForpostViewModel = koinViewModel()) {

    val scope = rememberCoroutineScope()
    val viewState = forpostViewModel.forpostViewState.observeAsState()
    val bottomSheetState = rememberModalBottomSheetState(
        initialValue = ModalBottomSheetValue.Hidden
    )

    ModalBottomSheetLayout(
        sheetState = bottomSheetState,
        sheetContent = {
            Box(modifier = Modifier
                .fillMaxWidth()
                .height(500.dp)) {
                Image(
                    painter = painterResource(id = R.drawable.botton_sheet_top_line),
                    contentDescription = "Линия",
                    modifier = Modifier
                        .height(20.dp)
                        .width(70.dp)
                        .padding(top = 10.dp)
                        .align(Alignment.TopCenter)
                )
                Text(
                    text = stringResource(id = R.string.all_cams_button),
                    color = colorResource(id = R.color.title_text_color),
                    fontWeight = FontWeight(600),
                    fontSize = 25.sp,
                    modifier = Modifier
                        .padding(top = 30.dp)
                        .align(Alignment.TopCenter)
                )
            }
        },
        sheetShape = RoundedCornerShape(topStart = 25.dp, topEnd = 25.dp),
        sheetElevation = 12.dp,
        // 核心:根据弹窗状态设置背景遮罩颜色
        scrimColor = if (bottomSheetState.isVisible) Color.Black.copy(alpha = 0.5f) else Color.Transparent
    ) {
        Surface(color = Color.White) {
            Column {
                Button(
                    onClick = {
                        scope.launch {
                            bottomSheetState.show()
                        }
                    },
                    colors = ButtonDefaults.buttonColors(colorResource(id = R.color.button_color)),
                    shape = RoundedCornerShape(15.dp),
                    modifier = Modifier
                        .padding(top = 20.dp, start = 20.dp)
                        .height(30.dp)
                        .width(130.dp),
                    contentPadding = PaddingValues(bottom = 0.dp),
                    content = {
                        Text(
                            text = stringResource(id = R.string.all_cams_button),
                            color = Color.White,
                            fontWeight = FontWeight(400)
                        )
                    }
                )

                Text(
                    modifier = Modifier.padding(top = 50.dp, start = 20.dp),
                    text = "Репина, 1 Б",
                    color = colorResource(id = R.color.title_text_color),
                    fontWeight = FontWeight(700),
                    fontSize = 18.sp,
                    letterSpacing= 1.sp
                )

                ButtonsLazyColumn(
                    listItem = listOf("Двор", "Подъезд", "Парковка", "Въезд", "Пост охраны"),
                    height = 50,
                    modifierPaddingStart = 20,
                    modifierPaddingTop = 15,
                    modifierPaddingEnd = 10,
                )

                Surface(modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 20.dp)
                    .height(220.dp)
                    .background(Color.Black)) {
                    when (viewState.value) {
                        is ForpostViewState.Loading -> { VideoLoadingView() }
                        is ForpostViewState.Load -> { PlayerView(forpostViewModel = forpostViewModel) }
                        else -> {}
                    }
                }

                Divider(
                    modifier = Modifier.padding(top = 100.dp),
                    color = colorResource(id = R.color.sevstar_gray_light),
                    thickness = 1.dp
                )

                ButtonsLazyColumn(
                    listItem = listOf("1 сек", "1 мин", "5 мин", "10 мин", "30 мин"),
                    height = 50,
                    modifierPaddingStart = 20,
                    modifierPaddingTop = 15,
                    modifierPaddingEnd = 10
                )

                Divider(
                    modifier = Modifier.padding(top = 20.dp),
                    color = colorResource(id = R.color.sevstar_purple),
                    thickness = 1.dp
                )
            }
        }
    }

    LaunchedEffect(key1 = viewState, block = {
        forpostViewModel.obtainEvent(event = ForpostEvents.EnterScreen)
    })
}

关键说明

  • scrimColor是ModalBottomSheetLayout的内置属性,专门用于控制弹窗打开时的背景遮罩颜色;
  • 当弹窗显示时,scrimColor会自动覆盖在底层内容之上,既实现变暗效果,又阻止底层控件的点击事件;
  • 移除了冗余的bottomSheetOpen状态,直接通过bottomSheetState.isVisible判断弹窗状态,代码更简洁可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 06:05:24