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

如何在Jetpack Compose中正确获取SystemBars高度并适配全屏布局

问题分析与解决方案

核心问题是单位不匹配:getInsets()返回的是像素值,而LocalConfiguration.current.screenHeightDp是dp单位,直接将像素转成dp(insetStatusBar.dp)会导致数值被错误放大(比如136像素在3倍密度设备上会被当成136dp,实际仅约45dp),这就是你看到Insets数值远大于screenHeightDp、布局重叠的原因。

正确处理步骤

1. 统一单位:像素转dp

使用Compose提供的LocalDensity将Insets的像素值转换为dp,保证计算时单位一致:

val density = LocalDensity.current
val insetStatusBarDp = with(density) { insetSystemBar.top.toDp() }
val insetNavBarDp = with(density) { insetSystemBar.bottom.toDp() }

2. 改用Compose原生WindowInsets API(更推荐)

直接从Compose的WindowInsets获取系统栏Insets,无需从View手动获取,适配性更好:

val systemBarsInsets = WindowInsets.systemBars.asPaddingValues()
val statusBarHeight = systemBarsInsets.calculateTopPadding()
val navBarHeight = systemBarsInsets.calculateBottomPadding()

3. 正确计算布局高度

要实现上下各占可用屏幕高度的一半(扣除系统栏后的区域),优先用Modifier.weight(1f)让两个Box自动平分可用空间,这是最简洁的方式;若需手动计算,先算出总可用高度再均分。

修改后的完整代码

方式一:用weight自动平分(推荐,无需手动计算)

让Compose自动处理布局分配,同时适配系统栏Insets:

@Composable
fun MyBox() {
    MyBoxTheme {
        Surface(Modifier.fillMaxSize()) {
            Column(
                Modifier
                    .fillMaxSize()
                    .background(Color(0xFF00B8D4))
                    // 若要让布局延伸到系统栏后方,可去掉此行,自行处理内部内容的padding
                    .windowInsetsPadding(WindowInsets.systemBars)
            ) {
                Box(
                    modifier = Modifier
                        .weight(1f)
                        .fillMaxWidth()
                        .background(Color(0x8FFFDD03))
                )
                Box(
                    modifier = Modifier
                        .weight(1f)
                        .fillMaxWidth()
                        .background(Color(0x86FF0303))
                )
            }
        }
    }
}

方式二:手动计算高度(适合精确控制场景)

修正单位问题后,手动计算各部分高度:

@Composable
fun MyBox() {
    val density = LocalDensity.current
    // 获取Compose原生系统栏Insets
    val systemBarsInsets = WindowInsets.systemBars.getInsets(density)
    val statusBarHeight = systemBarsInsets.top.toDp()
    val navBarHeight = systemBarsInsets.bottom.toDp()

    val configuration = LocalConfiguration.current
    val screenHeightDp = configuration.screenHeightDp.dp
    // 计算可用高度:总屏幕高度 - 状态栏 - 导航栏
    val availableHeight = screenHeightDp - statusBarHeight - navBarHeight
    val halfHeight = availableHeight / 2

    MyBoxTheme {
        Surface(Modifier.fillMaxSize()) {
            Box(
                Modifier
                    .fillMaxSize()
                    .background(Color(0xFF00B8D4))
            ) {
                Box(
                    modifier = Modifier
                        .height(halfHeight + navBarHeight)
                        .fillMaxWidth()
                        .align(Alignment.BottomCenter)
                        .background(Color(0x86FF0303))
                )

                Box(
                    modifier = Modifier
                        .height(halfHeight + statusBarHeight)
                        .fillMaxWidth()
                        .align(Alignment.TopCenter)
                        .background(Color(0x8FFFDD03))
                )
            }
        }
    }
}

额外注意事项

  • 开启Edge-to-edge模式时,需确保Activity已调用enableEdgeToEdge(),并适配系统栏图标颜色(如设置systemBarContrastEnforced = false)。
  • 不要依赖固定Insets数值,不同设备(折叠屏、刘海屏)的系统栏高度差异大,Compose的WindowInsets API会自动适配这些场景。

内容的提问来源于stack exchange,提问作者X-Black...

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 08:55:12