如何动态调整edge to edge模式下状态栏图标的颜色?
动态调整状态栏图标颜色适配Edge to Edge模式
在Edge to Edge模式下,要解决状态栏图标颜色与下方背景不兼容的问题,核心思路是实时检测状态栏对应区域的背景亮度,动态切换windowLightStatusBar的状态。以下是几种可行的实现方案:
方案1:监听滚动视图的滚动事件(适配RecyclerView/ScrollView)
通过监听滚动控件的滚动状态,实时获取状态栏下方可见区域的背景色,计算亮度后切换图标颜色。
步骤:
- 计算状态栏高度:
val statusBarHeight = resources.getDimensionPixelSize( resources.getIdentifier("status_bar_height", "dimen", "android") )
- 为RecyclerView添加滚动监听:
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { super.onScrolled(recyclerView, dx, dy) // 获取当前顶部可见的itemView val firstVisibleView = recyclerView.layoutManager?.findViewByPosition(0) ?: return // 截取状态栏对应区域的图像 val rect = Rect(0, 0, recyclerView.width, statusBarHeight) val bitmap = Bitmap.createBitmap(recyclerView.width, statusBarHeight, Bitmap.Config.ARGB_8888) val canvas = Canvas(bitmap) firstVisibleView.draw(canvas) val pixelColor = bitmap.getPixel(recyclerView.width/2, statusBarHeight/2) bitmap.recycle() // 计算颜色亮度(标准公式:0.299R + 0.587G + 0.114B) val brightness = (Color.red(pixelColor) * 0.299 + Color.green(pixelColor) * 0.587 + Color.blue(pixelColor) * 0.114).toInt() val isLightBackground = brightness > 128 // 动态切换状态栏图标颜色 updateStatusBarIconColor(isLightBackground) } })
- 实现跨版本的图标颜色切换方法:
private fun updateStatusBarIconColor(isLightBackground: Boolean) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { window.insetsController?.let { controller -> val appearance = if (isLightBackground) { WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS } else { 0 } controller.setSystemBarsAppearance(appearance, WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS) } } else { @Suppress("DEPRECATION") val systemUiVisibility = window.decorView.systemUiVisibility window.decorView.systemUiVisibility = if (isLightBackground) { systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR } else { systemUiVisibility and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() } } }
方案2:通过ViewTreeObserver监听绘制事件
如果页面是动态变化的非滚动布局,可以通过监听视图绘制事件,实时检测状态栏区域的背景色:
rootView.viewTreeObserver.addOnDrawListener(object : ViewTreeObserver.OnDrawListener { override fun onDraw() { val rect = Rect(0, 0, rootView.width, statusBarHeight) val bitmap = Bitmap.createBitmap(rootView.width, statusBarHeight, Bitmap.Config.ARGB_8888) val canvas = Canvas(bitmap) rootView.draw(canvas) val pixelColor = bitmap.getPixel(rootView.width/2, statusBarHeight/2) bitmap.recycle() val brightness = (Color.red(pixelColor) * 0.299 + Color.green(pixelColor) * 0.587 + Color.blue(pixelColor) * 0.114).toInt() val isLightBackground = brightness > 128 updateStatusBarIconColor(isLightBackground) } })
方案3:Android 13+ 原生对比度强制(可选)
在Android 13(API 33)及以上版本,可启用系统自动对比度处理,无需手动计算:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { window.statusBarContrastEnforced = true }
该方法让系统自动确保状态栏图标与背景的对比度,但仅适配高版本设备。
内容的提问来源于stack exchange,提问作者SmallGrammer
相关产品推荐
相关产品推荐

