第一章 基础概念
第01节 沉浸式
通俗的开发和日常使用语境中,通常是指让应用的内容铺满整个屏幕,将系统的状态栏(Top Bar,显示时间电量的地方)和导航栏(Bottom Bar,底部的虚拟按键或手势横条)与应用完美的融合在一起。
在传统的安卓界面中,系统栏和应用内容是"割裂"的:
- 传统非沉浸式:屏幕最上方是一条黑乎乎的系统状态栏,最下方是一条黑色的虚拟导航栏。应用的内容被死死地"夹"在中间。这种设计在全面屏时代显得非常过时,浪费屏幕空间。
- 现代沉浸式(端到端 Edge-to-Edge):应用的背景、图片或颜色直接延伸到了屏幕的最顶端和最底端,把状态栏和导航栏"包裹"在里面。系统图标(如时间、Wifi、电量)就像是直接悬浮在你的应用画面之上一样。
最终目的就是抹去系统界面与应用界面之间的那条"三八线",让用户在使用应用时,感觉整个屏幕都是为了这个应用而生的。
通过下面的一张图片,我们简单理解一下 非沉浸式 和 沉浸式的区别。(对于已经有过 N年开发经验的同仁而言,这部分内容非常的简单,无需做过多的解释)

第02节 存在需求
如果我们在做 安卓开发的过程中,出现了需求:要求状态栏或者底部菜单栏,是沉浸式的,应该如何实现呢?
目前市面上,采用的大多数是以前旧的写法,对于一些旧的写法而言,大多数已经被加上 过时 的注解。 @Deprecated
已经过时了!
你会发现,目前写的代码当中,大多数存在 删除线在代码上,那是因为在目前(2026年)的版本而言,已经被 Google 判定为过时的方案。
针对于比较新的版本(目前来说是 2026 年左右的版本) 来说,应该采用什么操作呢?
下面,我 将从 两个方面介绍 Android 11、12、13、14 以及 Android 15 等以上的版本,应该如何处理沉浸式。
分别是 Java 代码的版本 和 Kotlin 代码的版本。
第二章 Kotlin 版本
如果我们的代码是 kotlin 实现的,那么我们需要做下面的几点操作。
第01节 定义一个单例
定义一个单例 object 代码如下:
kotlin
import android.view.View
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
/**
* 通用状态栏和导航栏处理工具类
*
* 提供扩展函数来处理系统窗口 insets,确保视图在状态栏和导航栏区域正确显示
*/
object CommonStatusBar {
/**
* 为视图应用状态栏顶部内边距
*
* 此函数会监听窗口 insets 变化,并自动调整视图的顶部内边距以适配状态栏高度
* 保留视图原有的顶部内边距,并在其基础上增加状态栏高度
*
* @receiver View 需要应用状态栏内边距的视图
*/
fun View.applyStatusBarPadding() {
// 保存视图初始的顶部内边距
val initialTopPadding = this.paddingTop
// 设置窗口 insets 监听器,当系统窗口布局变化时回调
ViewCompat.setOnApplyWindowInsetsListener(this) { view, windowInsets ->
// 获取状态栏区域的 insets 信息
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.statusBars())
// 更新视图顶部内边距:原始内边距 + 状态栏高度
view.updatePadding(top = initialTopPadding + insets.top)
// 返回处理后的窗口 insets
windowInsets
}
}
/**
* 为视图应用导航栏底部内边距
*
* 此函数会监听窗口 insets 变化,并自动调整视图的底部内边距以适配导航栏高度
* 保留视图原有的底部内边距,并在其基础上增加导航栏高度
*
* @receiver View 需要应用导航栏内边距的视图
*/
fun View.applyNavigationBarPadding() {
// 保存视图初始的底部内边距
val initialBottomPadding = this.paddingBottom
// 设置窗口 insets 监听器,当系统窗口布局变化时回调
ViewCompat.setOnApplyWindowInsetsListener(this) { view, windowInsets ->
// 获取导航栏区域的 insets 信息
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars())
// 更新视图底部内边距:原始内边距 + 导航栏高度
view.updatePadding(bottom = initialBottomPadding + insets.bottom)
// 返回处理后的窗口 insets
windowInsets
}
}
}
第02节 修改 Activity
例如: 我们的布局文件如下
xml
<LinearLayout
android:id="@+id/topBarContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView android:id="@+id/" ... />
<TextView android:id="@+id/" ... />
<ImageView android:id="@+id/" ... />
</LinearLayout>
<LinearLayout
android:id="@+id/bottomBarContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView android:id="@+id/" ... />
<TextView android:id="@+id/" ... />
<ImageView android:id="@+id/" ... />
</LinearLayout>
那么我们可以这样编写代码
kotlin
override fun onCreate(savedInstanceState: Bundle?) {
// 建议在 super.onCreate(savedInstanceState) 上面添加。 (这里是建议写在 上面)
// 下面的代码, 来自于 import androidx.activity.enableEdgeToEdge
enableEdgeToEdge()
super.onCreate(savedInstanceState)
setContentView(binding.root)
// 只让外层大总管(容器)向下整体偏移状态栏高度
// 里面的所有按钮会自动跟着一起整齐地下移,绝对不会错位
binding.topBarContainer.applyStatusBarPadding()
// 如果底部也有多个并列按钮,同理打包给底部的布局容器
binding.bottomBarContainer.applyNavigationBarPadding()
}
第三章 Java 版本
如果我们的代码是 Java 实现的,那么我们需要做下面的几点操作。
第01节 定义一个工具类
java
import android.view.View;
import androidx.core.graphics.Insets;
import androidx.core.view.OnApplyWindowInsetsListener;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
/**
* 状态栏处理工具类
*
* 提供静态方法来处理系统窗口 insets,确保视图在状态栏区域正确显示
*/
public class StatusBarUtil {
/**
* 为视图应用状态栏顶部内边距
*
* 此方法会监听窗口 insets 变化,并自动调整视图的顶部内边距以适配状态栏高度
* 保留视图原有的顶部内边距,并在其基础上增加状态栏高度
*
* @param view 需要应用状态栏内边距的视图,如果为 null 则直接返回
*/
public static void applyStatusBarPadding(View view) {
// 空值检查,如果视图为 null 则直接返回
if (view == null) return;
// 保存视图初始的顶部内边距
final int initialTopPadding = view.getPaddingTop();
// 设置窗口 insets 监听器,当系统窗口布局变化时回调
ViewCompat.setOnApplyWindowInsetsListener(view, new OnApplyWindowInsetsListener() {
@Override
public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat windowInsets) {
// 获取状态栏区域的 insets 信息
Insets statusBarInsets = windowInsets.getInsets(WindowInsetsCompat.Type.statusBars());
// 更新视图顶部内边距:原始内边距 + 状态栏高度,保持其他方向内边距不变
v.setPadding(v.getPaddingLeft(), initialTopPadding + statusBarInsets.top, v.getPaddingRight(), v.getPaddingBottom());
// 返回处理后的窗口 insets
return windowInsets;
}
});
}
}
第02节 修改 Activity
例如: 我们的布局文件如下
xml
<LinearLayout
android:id="@+id/topBarContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView android:id="@+id/" ... />
<TextView android:id="@+id/" ... />
<ImageView android:id="@+id/" ... />
</LinearLayout>
<LinearLayout
android:id="@+id/bottomBarContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView android:id="@+id/" ... />
<TextView android:id="@+id/" ... />
<ImageView android:id="@+id/" ... />
</LinearLayout>
那么我们可以这样编写代码
java
protected void onCreate(@Nullable Bundle savedInstanceState) {
// 建议在 super.onCreate(savedInstanceState) 上面添加。 (这里是建议写在 上面)
// 下面的代码, 来自于 import androidx.activity.enableEdgeToEdge
EdgeToEdge.enable(this);
super.onCreate(savedInstanceState);
setContentView(binding.getRoot());
// 只让外层大总管(容器)向下整体偏移状态栏高度
// 里面的所有按钮会自动跟着一起整齐地下移,绝对不会错位
StatusBarUtil.applyStatusBarPadding(binding.topBarContainer);
// 如果底部也有多个并列按钮,同理打包给底部的布局容器
StatusBarUtil.applyStatusBarPadding(binding.bottomBarContainer);
}