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

Jetpack Compose如何实现Modal Bottom Sheet遮罩色显示在状态栏的效果

问题原因

默认ModalBottomSheetLayout的遮罩绘制范围仅限自身布局占用的区域,默认布局不会延伸到系统状态栏区域,因此遮罩无法覆盖状态栏。

解决步骤

1. 配置Activity窗口参数

首先需要让应用内容可以绘制到状态栏区域,在你的ActivityonCreate方法中添加如下配置:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // 设置状态栏透明
    window.statusBarColor = android.graphics.Color.TRANSPARENT
    // 允许内容绘制到系统栏区域
    WindowCompat.setDecorFitsSystemWindows(window, false)
}

如果你的项目已经开启了Edge-To-Edge显示,这一步可以跳过。

2. 修改Compose布局代码

给最外层的ModalBottomSheetLayout添加Modifier,让它的绘制范围覆盖全屏包括状态栏,内部的Scaffold正常处理系统栏间距即可,修改后的代码如下:

val modalBottomSheetState = rememberModalBottomSheetState(
    initialValue = ModalBottomSheetValue.Hidden,
)
val coroutineScope = rememberCoroutineScope()
// 可自定义遮罩颜色,这里用默认值
val scrimColor = ModalBottomSheetDefaults.scrimColor

ModalBottomSheetLayout(
    sheetState = modalBottomSheetState,
    sheetContent = {
        // 原有底部弹窗内容
    },
    scrimColor = scrimColor,
    // 关键:让布局填充全屏,包含状态栏区域
    modifier = Modifier.fillMaxSize()
) {
    Scaffold(
        scaffoldState = scaffoldState,
        topBar = {
            // 原有TopBar代码,添加statusBarsPadding避免内容和状态栏重叠
            TopAppBar(
                modifier = Modifier.statusBarsPadding(),
                title = { Text("页面标题") }
            )
        },
        floatingActionButton = {
            FloatingActionButton(
                onClick = {
                    coroutineScope.launch {
                        if (!modalBottomSheetState.isAnimationRunning) {
                            if (modalBottomSheetState.isVisible) {
                                modalBottomSheetState.hide()
                            } else {
                                modalBottomSheetState.show()
                            }
                        }
                    }
                },
            ) {
                Icon(
                    imageVector = Icons.Rounded.Add,
                    contentDescription = "Add",
                )
            }
        },
        modifier = Modifier.fillMaxSize(),
    ) { innerPadding ->
        // 原有页面内容代码,处理innerPadding即可
        Box(Modifier.padding(innerPadding)) {
            // 页面内容
        }
    }
}

备选兼容方案

如果上述方案在你的设备/依赖版本上有适配问题,可以通过监听底部弹窗的状态动态修改状态栏颜色,和遮罩动画同步:

// 记录页面原始状态栏颜色
val originalStatusBarColor = remember { window.statusBarColor }
val scrimColor = ModalBottomSheetDefaults.scrimColor

// 跟随弹窗展开进度同步修改状态栏颜色
LaunchedEffect(modalBottomSheetState.progress) {
    val alpha = modalBottomSheetState.progress.fraction
    val blendedColor = ColorUtils.blendARGB(originalStatusBarColor, scrimColor.toArgb(), alpha)
    window.statusBarColor = blendedColor
}
// 弹窗完全隐藏后恢复原始状态栏颜色
LaunchedEffect(modalBottomSheetState.isVisible) {
    if (!modalBottomSheetState.isVisible) {
        window.statusBarColor = originalStatusBarColor
    }
}

效果对比

  • 原有View体系预期效果:View体系Modal Bottom Sheet效果
  • 改造前Compose实现效果:原有Compose Modal Bottom Sheet效果
  • 改造后效果和View体系效果完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 06:39:02