ComponentActivity.enableEdgeToEdge在Api35下无法修改状态栏背景色的原因及解决
compileSdkVersion 35下ComponentActivity.enableEdgeToEdge无法修改状态栏背景色的问题分析与解决
问题描述
原本可通过ComponentActivity.enableEdgeToEdge()扩展修改状态栏背景色,但将compileSdkVersion升级到35后,状态栏始终呈透明状态,仅修改状态栏指示器颜色的代码仍正常工作:
fun Activity.setupStatusBarIndicatorsColor(isLightStatusBar: Boolean) { WindowCompat.getInsetsController(window, window.decorView).isAppearanceLightStatusBars = !isLightStatusBar && isLightMode }
成因分析
Android 15(对应API 35)对ComponentActivity.enableEdgeToEdge()的实现逻辑做了调整:该方法现在会强制将状态栏背景色设置为透明,同时启用系统Insets的自动适配逻辑。原来在调用该方法后设置状态栏背景色的代码会被系统的透明设置覆盖,导致自定义背景色失效。而状态栏指示器颜色的修改逻辑独立于背景色设置,通过WindowCompat.getInsetsController()操作的是状态栏图标/文字的主题属性,因此不受影响。
解决方法
方法1:手动实现边缘到边缘布局,放弃使用enableEdgeToEdge()
直接通过Window API启用边缘到边缘布局,同时自定义状态栏背景色,避免系统自动覆盖:
fun Activity.setupCustomEdgeToEdge(statusBarColor: Int, isLightStatusBar: Boolean) { // 关闭DecorView自动适配系统窗口Insets window.setDecorFitsSystemWindows(false) // 设置状态栏背景色 window.statusBarColor = statusBarColor // 处理状态栏指示器颜色 WindowCompat.getInsetsController(window, window.decorView).isAppearanceLightStatusBars = !isLightStatusBar && isLightMode }
方法2:调用enableEdgeToEdge()后重新设置状态栏背景色
如果仍需保留enableEdgeToEdge()的其他适配逻辑,可在调用该方法后立即覆盖状态栏背景色:
fun ComponentActivity.setupEdgeToEdgeWithCustomStatusBar(statusBarColor: Int, isLightStatusBar: Boolean) { enableEdgeToEdge() // 重新设置状态栏背景色,覆盖系统的透明设置 window.statusBarColor = statusBarColor // 处理指示器颜色 setupStatusBarIndicatorsColor(isLightStatusBar) }
方法3:通过DecorView添加独立状态栏背景View
若上述方法仍有冲突,可在DecorView中添加一个与状态栏等高的View作为背景,避开系统Insets的影响:
fun Activity.setupStatusBarBackground(statusBarColor: Int, isLightStatusBar: Boolean) { enableEdgeToEdge() // 创建状态栏背景View val statusBarView = View(this).apply { setBackgroundColor(statusBarColor) layoutParams = ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, resources.getDimensionPixelSize(android.R.dimen.status_bar_height) ) } // 添加到DecorView val decorView = window.decorView as ViewGroup decorView.addView(statusBarView) // 确保内容布局避开状态栏区域 ViewCompat.setOnApplyWindowInsetsListener(findViewById(android.R.id.content)) { view, insets -> val insetsStatusBar = insets.getInsets(WindowInsetsCompat.Type.statusBars()) (view.layoutParams as ViewGroup.MarginLayoutParams).topMargin = insetsStatusBar.top insets } // 处理指示器颜色 setupStatusBarIndicatorsColor(isLightStatusBar) }
内容的提问来源于stack exchange,提问作者Petro
相关产品推荐
相关产品推荐

