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

Jetpack Compose中显示Admob插屏广告时界面内容偏移至状态栏下的解决办法

解决Jetpack Compose中enableEdgeToEdge()导致的UI偏移问题

当使用enableEdgeToEdge()或WindowCompat.setDecorFitsSystemWindows(window, false)实现Compose自定义系统栏背景后,打开全屏广告、应用选择器、Google Play内评等上层界面返回时,原Activity的UI会出现偏移到状态栏下方的问题。根源是上层界面销毁后,系统会重置窗口的fitsSystemWindows属性,导致Compose的insets计算失效。

以下是几种可行的解决方案,其中方案1为最优解:

方案1:在Activity生命周期中重新启用Edge-to-Edge并触发重组

通过重写onResume方法,每次从上层界面返回时重新应用edge-to-edge配置,并触发Compose重组以重新计算正确的insets:

class MainActivity : ComponentActivity() {
    private var interstitialAd: InterstitialAd? = null
    // 用于触发Compose重组的状态标记
    private val recomposeTrigger = mutableStateOf(false)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ... 加载广告逻辑

        enableEdgeToEdge()
        setContent {
            AppTheme {
                // 监听状态变化,触发重组后重置标记
                if (recomposeTrigger.value) {
                    SideEffect { recomposeTrigger.value = false }
                }
                
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    Column(modifier = Modifier.padding(innerPadding)) {
                        Button(onClick = {
                            interstitialAd?.show(this@MainActivity)
                        }) {
                            Text(text = "Show fullscreen ad")
                        }
                    }
                }
            }
        }
    }

    override fun onResume() {
        super.onResume()
        // 重新启用edge-to-edge配置
        enableEdgeToEdge()
        // 触发Compose重组,重新计算insets
        recomposeTrigger.value = true
    }
}

方案2:手动监听WindowInsets并控制布局padding

不依赖Scaffold的innerPadding,直接获取实时WindowInsets来设置布局的padding,确保始终适配系统栏:

setContent {
    AppTheme {
        val windowInsets = WindowInsets.current
        val statusBarHeight = windowInsets.statusBars.top.dp
        val navigationBarHeight = windowInsets.navigationBars.bottom.dp
        
        Scaffold(modifier = Modifier.fillMaxSize()) { scaffoldPadding ->
            Column(
                modifier = Modifier
                    .padding(
                        top = max(scaffoldPadding.calculateTopPadding(), statusBarHeight),
                        bottom = max(scaffoldPadding.calculateBottomPadding(), navigationBarHeight),
                        start = scaffoldPadding.calculateStartPadding(LayoutDirection.Ltr),
                        end = scaffoldPadding.calculateEndPadding(LayoutDirection.Ltr)
                    )
            ) {
                Button(onClick = {
                    interstitialAd?.show(this@MainActivity)
                }) {
                    Text(text = "Show fullscreen ad")
                }
            }
        }
    }
}

方案3:手动维护Window的fitsSystemWindows状态

直接通过WindowCompat强制设置fitsSystemWindows为false,并同步系统栏样式,再触发重组:

override fun onResume() {
    super.onResume()
    // 强制关闭系统栏自动适配
    WindowCompat.setDecorFitsSystemWindows(window, false)
    // 重新设置系统栏亮色/暗色模式(根据你的主题调整)
    WindowCompat.getInsetsController(window, window.decorView).apply {
        isAppearanceLightStatusBars = true
        isAppearanceLightNavigationBars = true
    }
    // 触发Compose重组
    recomposeTrigger.value = true
}

最佳实践

方案1是最简洁且通用的解决方式,它利用Activity的生命周期回调覆盖系统的状态重置,同时通过状态标记触发Compose重新计算布局,适配所有导致窗口状态变化的场景(包括广告、选择器、内评等)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 04:00:20