透明状态栏和透明导航栏

设置Window Flag要在setContentView前。不在前目前发现改变状态栏不会生效

实现透明状态栏

透明状态栏以来官方提供的API,重要改动主要有三个:

  1. Android 4.4
  2. Android 5.0
  3. Android 6.0

Android 4.4

从4.4开始支持透明状态栏,这个版本是半透明,有一层遮罩:

Android 5.0

真正支持透明状态栏,可以设置状态栏的颜色。

实现方式

给window中的DecorView设置*systemUiVisibilityView.*SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN*View.*SYSTEM_UI_FLAG_LAYOUT_STABLE

同时给window添加flag:FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS

含义

SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN:状态栏和导航栏悬浮在View上方

SYSTEM_UI_FLAG_LAYOUT_STABLE:让状态栏、导航栏稳定,不随输入状态改变。

FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS:绘制的内容可以到状态栏和导航栏的区域。

Android 6.0

支持了导航栏上icon和文字颜色的反色

也是通过window中的DecorView设置*systemUiVisibility。*

亮色状态栏:View.*SYSTEM_UI_FLAG_LIGHT_STATUS_BAR*

暗色状态栏:View.*SYSTEM_UI_FLAG_LIGHT_STATUS_BAR*

Android 11

弃用Flag的形式。

内容可以绘制到状态栏和导航栏的区域:

WindowCompat.setDecorFitsSystemWindows(window, false)

状态栏颜色要求使用WindowInsetsController,或是兼容的WindowInsetsControllerCompat

val windowInsetsControllerCompat =
                WindowCompat.getInsetsController(window, window.decorView)
windowInsetsControllerCompat.isAppearanceLightStatusBars = true

DecorView上加了marginBottom,底部的navigationBar不见了

默认的navigationBar在DecorViewView中LinearLayout的下面,紧挨着。 statusBar添加flag后是悬浮在ContentView上方。

猜测是因为默认的flag的关系。具体不清楚 从代码可以确定是因为设置marginBottom让NavigationBar不显示了。

💡 使用官方推荐的setOnApplyWindowInsetsListener更合适,通过dimen拿到高度不准确,且在隐藏时是0。

setOnApplyWindowInsetsListener调用时机:

从ViewGroup分发至子View,流程类似事件分发中的View分发部分,开始的源头则是ViewRootImpl调用布局绘制performTraversals的方法

另一种途径是调用了requestFitSystemWindows方法,其实还是因为需要重新布局绘制。