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

如何为Jetpack Compose的BottomSheetScaffold设置半透明黑色背景

解决Jetpack Compose BottomSheetScaffold半透明遮罩设置问题

问题原因

你现在设置的sheetBackgroundColor = Color.Transparent只会修改底部sheet本身的背景色,而BottomSheetScaffold默认不会自带底层半透明遮罩,所以无法实现你要的类似XML中BottomSheetDialogFragment的背景效果。

解决方案

方案1:在现有BottomSheetScaffold基础上手动添加遮罩层

监听底部sheet的展开状态,在主内容上方叠加半透明遮罩即可,修改后代码如下:

@Composable
fun BottomSheet(
    modifier: Modifier = Modifier,
    title: String,
    content: String,
    buttonText: String,
    composable: @Composable () -> Unit,
    isOpen: (Boolean) -> Unit
) {
    val coroutineScope = rememberCoroutineScope()
    val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
        bottomSheetState = BottomSheetState(BottomSheetValue.Expanded)
    )
    // 判断是否需要显示遮罩
    val showScrim = bottomSheetScaffoldState.bottomSheetState.isExpanded

    BottomSheetScaffold(
        sheetBackgroundColor = Color.Transparent,
        scaffoldState = bottomSheetScaffoldState,
        sheetGesturesEnabled = false,
        sheetContent = {
            // 给sheet内容加白色背景,不然内容也会透明
            Column(
                Modifier
                    .fillMaxWidth()
                    .background(
                        color = Color.White,
                        shape = RoundedCornerShape(topEnd = medium, topStart = medium)
                    )
                    .padding(8.dp),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                Text(
                    text = title,
                    style = AppFont.PoppinsTypography.button
                )
                Spacer(modifier = modifier.size(8.dp))
                Text(
                    text = content,
                    style = AppFont.PoppinsTypography.body1
                )
                Spacer(modifier = modifier.size(16.dp))
                Button(colors = ButtonDefaults.buttonColors(
                    backgroundColor = AppColor.brandColor.BLUE_DE_FRANCE,
                    contentColor = AppColor.neutralColor.DOCTOR
                ),
                    shape = RoundedCornerShape(
                        small
                    ),
                    onClick = {
                        coroutineScope.launch {
                            bottomSheetScaffoldState.bottomSheetState.collapse()
                            isOpen.invoke(false)
                        }
                    }) {
                    Text(
                        text = buttonText,
                        style = AppFont.PoppinsTypography.button
                    )
                }
            }
        },
        sheetShape = RoundedCornerShape(topEnd = medium, topStart = medium),
        sheetPeekHeight = 0.dp,
        drawerGesturesEnabled = false
    ) { innerPadding ->
        Box(modifier = Modifier
            .fillMaxSize()
            .padding(innerPadding)) {
            // 原有主内容
            composable()
            // 半透明遮罩层
            if (showScrim) {
                Spacer(modifier = Modifier
                    .fillMaxSize()
                    .background(Color.Black.copy(alpha = 0.5f))
                    .clickable(
                        // 去掉点击涟漪效果,和系统弹窗行为一致
                        indication = null,
                        interactionSource = remember { MutableInteractionSource() }
                    ) {
                        coroutineScope.launch {
                            bottomSheetScaffoldState.bottomSheetState.collapse()
                            isOpen(false)
                        }
                    }
                )
            }
        }
    }
}

方案2:改用官方ModalBottomSheetLayout(更推荐)

该组件是官方专门用来实现模态底部弹窗的,自带遮罩层,不需要手动写遮罩逻辑,效果和BottomSheetDialogFragment完全一致,实现代码如下:

@Composable
fun ModalBottomSheet(
    modifier: Modifier = Modifier,
    title: String,
    content: String,
    buttonText: String,
    composable: @Composable () -> Unit,
    isOpen: (Boolean) -> Unit
) {
    val coroutineScope = rememberCoroutineScope()
    val sheetState = rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden)
    
    // 初始自动展开弹窗
    LaunchedEffect(key1 = Unit) {
        sheetState.show()
    }
    
    // 监听弹窗关闭回调
    LaunchedEffect(key1 = sheetState.isVisible) {
        if (!sheetState.isVisible) {
            isOpen(false)
        }
    }

    ModalBottomSheetLayout(
        sheetState = sheetState,
        // 直接设置遮罩层颜色,调整alpha可以控制透明度
        scrimColor = Color.Black.copy(alpha = 0.5f),
        sheetShape = RoundedCornerShape(topStart = medium, topEnd = medium),
        sheetContent = {
            Column(
                Modifier
                    .fillMaxWidth()
                    .padding(8.dp),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                Text(
                    text = title,
                    style = AppFont.PoppinsTypography.button
                )
                Spacer(modifier = modifier.size(8.dp))
                Text(
                    text = content,
                    style = AppFont.PoppinsTypography.body1
                )
                Spacer(modifier = modifier.size(16.dp))
                Button(colors = ButtonDefaults.buttonColors(
                    backgroundColor = AppColor.brandColor.BLUE_DE_FRANCE,
                    contentColor = AppColor.neutralColor.DOCTOR
                ),
                    shape = RoundedCornerShape(small),
                    onClick = {
                        coroutineScope.launch {
                            sheetState.hide()
                        }
                    }) {
                    Text(
                        text = buttonText,
                        style = AppFont.PoppinsTypography.button
                    )
                }
            }
        }
    ) {
        composable()
    }
}

注意事项

  • 如果你使用的是Material3版本的Compose,ModalBottomSheet的API会有小幅度调整,核心逻辑不变,替换为对应版本的API即可。
  • 给sheet设置透明背景后,一定要给内容层加对应背景色,避免内容也变成透明。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 03:15:03