1. 什么是沉浸式状态栏

Android 里常说的“沉浸式状态栏”,其实包含几类需求:

需求

含义

状态栏变色

状态栏显示为业务页面指定颜色

透明状态栏

页面内容绘制到状态栏后面

Edge-to-edge

内容绘制到状态栏、导航栏、刘海区域后面

全屏沉浸

隐藏状态栏/导航栏,比如视频、游戏、阅读器

Insets 适配

内容进入系统栏区域后,标题栏、按钮、列表不能被遮挡

以前大家说“沉浸式状态栏”,更多是指:

状态栏透明 + 顶部布局延伸到状态栏下面。

现在更准确的说法应该是:

Edge-to-edge + WindowInsets 适配。


2. Android 各版本是如何解决的

Android 版本

API

系统能力

常见处理方式

Android 4.4

19

支持半透明状态栏 FLAG_TRANSLUCENT_STATUS

让内容进入状态栏区域,再加一个“假状态栏 View”占位

Android 5.0

21

支持 setStatusBarColor()

可以直接设置状态栏颜色,也可以设置透明

Android 6.0

23

支持状态栏深色图标

浅色背景状态栏终于可以配黑色图标

Android 8.0

26

支持导航栏深色图标

浅色导航栏可以配黑色图标

Android 9.0

28

官方支持刘海屏 API

使用 layoutInDisplayCutoutMode 处理刘海区域

Android 10

29

手势导航普及

需要考虑底部手势区域、导航栏透明、系统手势冲突

Android 11

30

WindowInsetsController 成为新方向

旧的 system UI flag 开始不推荐,建议用 Insets API

AndroidX Activity 1.8+

-

提供 enableEdgeToEdge()

用 AndroidX 统一处理 edge-to-edge 兼容

Android 15

35

target SDK 35 后默认 edge-to-edge

内容默认绘制到系统栏后面,必须处理 Insets

Android 官方现在明确说明:target SDK 35 后,在 Android 15 设备上应用会默认 edge-to-edge,内容会绘制到状态栏、导航栏后面;如果没有处理 Insets,UI 可能被遮挡。Android edge-to-edge 文档


3. 老版本为什么难适配

老版本难适配,不是因为代码复杂,而是因为系统能力不完整。

比如:

问题

原因

Android 4.4 不能真正设置状态栏颜色

只能半透明,所以经常要加假 View

Android 6.0 以下不能设置状态栏黑色图标

系统不支持,只能加深背景兜底

Android 8.0 以下导航栏黑色图标支持不好

浅色导航栏容易看不清

刘海屏早期没有统一 API

各家 ROM 有自己的适配方式

手势导航早期没有完整 Insets 概念

底部按钮、列表、输入框容易被遮挡

所以新的 SDK 可以统一很多写法,但不能让老系统凭空拥有新能力。


4. 以前的开源框架

以前做沉浸式状态栏,很多项目会用第三方框架。

框架

特点

现在建议

ImmersionBar

国内非常流行,支持 Activity、Fragment、Dialog、刘海屏、键盘等场景

老项目可以继续用,新项目不优先

StatusBarUtil

早期经典库,主要解决状态栏变色、透明、DrawerLayout 等

不建议新项目使用

UltimateBarX

支持状态栏、导航栏分开设置,适配国产 ROM、刘海屏等

老项目可以观察使用

SystemBarTint

Android 4.4 时代方案

基本属于历史方案

Accompanist System UI Controller

Compose 时代曾经常用

官方已 deprecated,建议迁移到 enableEdgeToEdge() / WindowInsetsControllerCompatAccompanist 文档

这些框架当年有价值,是因为它们帮我们处理了:

  1. Android 4.4 假状态栏。

  2. Android 5.0 状态栏颜色。

  3. Android 6.0 状态栏图标深浅色。

  4. 国产 ROM 差异。

  5. Fragment / Dialog / PopupWindow 场景。

  6. 刘海屏和键盘遮挡问题。

但是现在,官方 API 已经覆盖了大部分主流需求。


5. 现在推荐的解决方案

现在新项目一般不建议再引入第三方沉浸式状态栏框架,而是使用官方方案。

核心思路是:

  1. Activity 里开启 edge-to-edge。

  2. 页面内容允许绘制到系统栏后面。

  3. 使用 WindowInsets 给重要内容加 padding 或 margin。

  4. 顶部标题栏避开状态栏。

  5. 底部按钮、底部导航、列表最后一项避开导航栏。

  6. 需要全屏时再隐藏系统栏。

View 项目常用:

能力

推荐 API

开启 edge-to-edge

enableEdgeToEdge()WindowCompat.enableEdgeToEdge(window)

控制系统栏显示隐藏

WindowInsetsControllerCompat

获取状态栏/导航栏高度

WindowInsetsCompat

给 View 加避让距离

ViewCompat.setOnApplyWindowInsetsListener

RecyclerView 底部避让

设置 bottom padding,并设置 clipToPadding=false

Compose 项目常用:

能力

推荐方式

页面整体布局

Material3 Scaffold

顶部避让

statusBarsPadding()

底部避让

navigationBarsPadding()

系统栏 Insets

WindowInsets

全屏隐藏系统栏

WindowInsetsControllerCompat 或窗口 API


6. 现在兼容的重点变了

以前兼容的是:

  1. 状态栏怎么透明。

  2. 状态栏怎么变色。

  3. 状态栏图标怎么变黑。

  4. Android 4.4 / 5.0 / 6.0 怎么分别处理。

  5. 国产 ROM 怎么适配。

现在兼容的是:

  1. 内容不要被状态栏遮住。

  2. 内容不要被导航栏遮住。

  3. 列表最后一项不要被导航栏盖住。

  4. 底部按钮不要进入手势区域。

  5. 刘海屏、横屏、折叠屏要正常。

  6. Android 15 默认 edge-to-edge 后页面不能乱。

也就是说:

以前是“状态栏效果适配”,现在是“系统栏 Insets 适配”。


7. 推荐理解流程


8. 实战建议

新项目建议:

  1. 不再优先引入 ImmersionBar、StatusBarUtil 这类框架。

  2. 直接使用 AndroidX 的 enableEdgeToEdge()

  3. 所有页面统一按 edge-to-edge 思路设计。

  4. 顶部 AppBar 处理状态栏高度。

  5. 底部导航、悬浮按钮、输入框处理导航栏高度。

  6. RecyclerView、NestedScrollView 处理底部 padding。

  7. Android 6.0 以下状态栏深色图标不支持时,用深色背景兜底。

  8. Android 15 设备必须重点测试。

老项目建议:

  1. 如果已经用了 ImmersionBar / UltimateBarX,可以暂时保留。

  2. 新页面尽量用官方 Insets 思路写。

  3. 不要继续扩散老的假状态栏方案。

  4. 逐步把“状态栏颜色适配”迁移成“WindowInsets 适配”。

  5. target SDK 升到 35 前,重点检查所有页面是否被状态栏、导航栏遮挡。


9. 总结

沉浸式状态栏的发展可以分成三个阶段:

阶段

核心思路

Android 4.4 - 5.0

通过半透明状态栏、假状态栏 View 实现视觉效果

Android 6.0 - 14

通过状态栏颜色、深浅图标、第三方库做兼容

Android 15 之后

官方默认 edge-to-edge,重点变成 Insets 适配

最终结论:

现在不是完全不需要兼容,而是不再建议围绕“状态栏颜色”做兼容,而应该围绕 WindowInsets 做兼容。

第三方框架还有历史价值,但新项目更推荐官方方案。
老版本系统不支持的能力,只能降级处理;新 SDK 可以统一写法,但不能彻底消除老系统限制。