安卓沉浸式写法

第一章 基础概念

第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);
}
相关推荐
zfoo-framework17 小时前
理解kotlin limitedParallelism(1)与Actor模型
android·开发语言·kotlin
plainGeekDev18 小时前
RecyclerView.Adapter → ListAdapter
java·kotlin·gradle
plainGeekDev19 小时前
findViewById → ViewBinding
java·kotlin·gradle
Kapaseker1 天前
用 Kotlin 构建你的第一个 Agent — 开篇
android·kotlin
三雒1 天前
KMP 实战:Android 开发如何快速统一双端 IM 模块
android·ios·kotlin
我是唐青枫1 天前
Kotlin let 详解:空安全、链式转换与实战示例
kotlin
唐青枫2 天前
Kotlin let 详解:空安全、链式转换与实战示例
kotlin
alexhilton2 天前
车载系统中的可扩展UI:从UI嵌入到系统窗口编排
android·kotlin·android jetpack
日光明媚3 天前
一步生成视频!One-Forcing:DMD + 零成本 GAN,训练 200 步超越多步 SOTA
android·开发语言·kotlin