Android动态控制状态栏显示和隐藏

发布时间 - 2026-01-11 00:47:48    点击率:

记得之前有朋友在留言里让我写一篇关于沉浸式状态栏的文章,正巧我确实有这个打算,那么本篇就给大家带来一次沉浸式状态栏的微技巧讲解。

其实说到沉浸式状态栏这个名字我也是感到很无奈,真不知道这种叫法是谁先发起的。因为Android官方从来没有给出过沉浸式状态栏这样的命名,只有沉浸式模式(Immersive Mode)这种说法。而有些人在没有完全了解清楚沉浸模式到底是什么东西的情况下,就张冠李戴地认为一些系统提供的状态栏操作就是沉浸式的,并且还起了一个沉浸式状态栏的名字。

比如之前就有一个QQ群友问过我,像饿了么这样的沉浸式状态栏效果该如何实现?

这个效果其实就是让背景图片可以利用系统状态栏的空间,从而能够让背景图和状态栏融为一体。

本篇文章当中我会教大家如何实现这样的效果,但这个真的不叫沉浸式状态栏。因此,这算是一篇技术+普及的文章吧,讲技术的同时也纠正一下大家之前错误的叫法。

什么是沉浸式?

先来分析一下叫错的原因吧,之所以很多人会叫错,是因为根本就不了解沉浸式是什么意思,然后就人云亦云跟着叫了。那么沉浸式到底是什么意思呢?

根据百度百科上的定义,沉浸式就是要给用户提供完全沉浸的体验,使用户有一种置身于虚拟世界之中的感觉。

比如说现在大热的VR就是主打的沉浸式体验。

那么对应到Android操作系统上面,怎样才算是沉浸式体验呢?这个可能在大多数情况下都是用不到的,不过在玩游戏或者看电影的时候就非常重要了。因为游戏或者*类的应用都希望能让用户完全沉浸在其中,享受它们提供的娱乐内容,但如果这个时候在屏幕的上方还显示一个系统状态栏的话,可能就会让用户分分钟产生跳戏的感觉。

那么我们来看一下比较好的游戏都是怎么实现的,比如说海岛奇兵:

海岛奇兵的这种模式就是典型的沉浸式模式,它的整个屏幕中显示都是游戏的内容,没有状态栏也没有导航栏,用户玩游戏的时候就可以完全沉浸在游戏当中,而不会被一些系统的界面元素所打扰。

然后我们再来看一下爱奇艺的实现:

 

同样也是类似的,爱奇艺将整个屏幕作为*的展示区,用户在看电影的时候眼中就只会有电影的内容,这样就不会被其他一些无关的东西所分心。

这才是沉浸式模式的真正含义,而所谓的什么沉浸式状态栏纯粹就是在瞎叫,完全都没搞懂“沉浸式” 这三个字是什么意思。

不过虽然听上去好像是很高大上的沉浸式效果,实际看上去貌似就是将内容全屏化了而已嘛。没错,Android沉浸式模式的本质就是全屏化,不过我们今天的内容并不仅限于此,因为还要实现饿了么那样的状态栏效果。那么下面我们就开始来一步步学习吧。

隐藏状态栏

可以看到,有状态栏、ActionBar、导航栏等。而打造沉浸式模式的用户体验,就是要将这些系统元素全部隐藏,只留下主体内容部分。

比如说我现在新建了一个空项目,然后修改布局文件中的代码,在里面加入一个ImageView,如下所示:

<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:src="@drawable/bg"
    android:scaleType="centerCrop" />

</RelativeLayout>

这里将ImageView的宽和高都设置成match_parent,让图片充满屏幕。现在运行一下程序,效果如下图所示。

 

如果你将图片理解成游戏或者电影界面的话,那这个体验离沉浸式就差得太远了,至少状态栏和ActionBar得要隐藏起来了吧?没关系,我们一步步进行优化,并且在优化中学习。

隐藏状态栏和ActionBar的方式在4.1系统之上和4.1系统之下还是不一样的,这里我就不准备考虑4.1系统之下的兼容性了,因为过于老的系统根本就没有提供沉浸式体验的支持。

修改MainActivity中的代码,如下所示:

public class MainActivity extends AppCompatActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    View decorView = getWindow().getDecorView();
    int option = View.SYSTEM_UI_FLAG_FULLSCREEN;
    decorView.setSystemUiVisibility(option);
    ActionBar actionBar = getSupportActionBar();
    actionBar.hide();
  }
}

这里先调用getWindow().getDecorView()方法获取到了当前界面的DecorView,然后调用它的setSystemUiVisibility()方法来设置系统UI元素的可见性。其中,SYSTEM_UI_FLAG_FULLSCREEN表示全屏的意思,也就是会将状态栏隐藏。另外,根据Android的设计建议,ActionBar是不应该独立于状态栏而单独显示的,因此状态栏如果隐藏了,我们同时也需要调用ActionBar的hide()方法将ActionBar也进行隐藏。

现在重新运行一下程序,效果如下图所示。

 

这样看上去就有点沉浸式效果的模样了。

虽说这才是正统的沉浸式含义,但有些朋友可能想实现的就是饿了么那样的状态栏效果,而不是直接把整个系统状态栏给隐藏掉,那么又该如何实现呢?

其实也很简单,只需要借助另外一种UI Flag就可以了,如下所示:

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= 21) {
  View decorView = getWindow().getDecorView();
  int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
      | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
  decorView.setSystemUiVisibility(option);
  getWindow().setStatusBarColor(Color.TRANSPARENT);
}
ActionBar actionBar = getSupportActionBar();
actionBar.hide();

首先需要注意,饿了么这样的效果是只有5.0及以上系统才支持,因此这里先进行了一层if判断,只有系统版本大于或等于5.0的时候才会执行下面的代码。

接下来我们使用了SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN和SYSTEM_UI_FLAG_LAYOUT_STABLE,注意两个Flag必须要结合在一起使用,表示会让应用的主体内容占用系统状态栏的空间,最后再调用Window的setStatusBarColor()方法将状态栏设置成透明色就可以了。

现在重新运行一下代码,效果如下图所示。

 

可以看到,类似于饿了么的状态栏效果就成功实现了。

再声明一次,这种效果不叫沉浸式状态栏,也完全没有沉浸式状态栏这种说法,我们估且可以把它叫做透明状态栏效果吧。

隐藏导航栏

现在我们已经成功实现隐藏状态栏的效果了,不过屏幕下方的导航栏还比较刺眼,接下来我们就学习一下如何将导航栏也进行隐藏。

其实实现的原理都是一样的,隐藏导航栏也就是使用了不同的UI Flag而已,修改MainActivity中的代码,如下所示:

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View decorView = getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
    | View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(option);
ActionBar actionBar = getSupportActionBar();
actionBar.hide();

这里我们同时使用了SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN,这样就可以将状态栏和导航栏同时隐藏了。现在重新运行一下程序,效果如图所示。

这次看上去好像终于是完全全屏化了,但其实上这离真正的沉浸式模式还差得比较远,因为在这种模式下,我们触摸屏幕的任意位置都会退出全屏。

 

这显然不是我们想要的效果,因此这种模式的使用场景比较有限。

除了隐藏导航栏之外,我们同样也可以实现和刚才透明状态栏类似的效果,制作一个透明导航栏:

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= 21) {
  View decorView = getWindow().getDecorView();
  int option = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
      | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
      | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
  decorView.setSystemUiVisibility(option);
  getWindow().setNavigationBarColor(Color.TRANSPARENT);
  getWindow().setStatusBarColor(Color.TRANSPARENT);
}
ActionBar actionBar = getSupportActionBar();
actionBar.hide();

这里使用了SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,表示会让应用的主体内容占用系统导航栏的空间,然后又调用了setNavigationBarColor()方法将导航栏设置成透明色。现在重新运行一下程序,效果如下图所示。

真正的沉浸式模式

虽说沉浸式导航栏这个东西是被很多人误叫的一种称呼,但沉浸式模式的确是存在的。那么我们如何才能实现像海岛奇兵以及爱奇艺那样的沉浸式模式呢?

首先你应该确定自己是否真的需要这个功能,因为除了像游戏或者视频软件这类特殊的应用,大多数的应用程序都是用不到沉浸式模式的。

当你确定要使用沉浸式模式,那么只需要重写Activity的onWindowFocusChanged()方法,然后加入如下逻辑即可:

public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
  }

  @Override
  public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus && Build.VERSION.SDK_INT >= 19) {
      View decorView = getWindow().getDecorView();
      decorView.setSystemUiVisibility(
        View.SYSTEM_UI_FLAG_LAYOUT_STABLE
        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
        | View.SYSTEM_UI_FLAG_FULLSCREEN
        | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
    }
  }

}

沉浸式模式的UI Flag就这些,也没什么好解释的,如果你需要实现沉浸式模式,直接将上面的代码复制过去就行了。需要注意的是,只有在Android 4.4及以上系统才支持沉浸式模式,因此这里也是加入了if判断。

另外,为了让我们的界面看上去更像是游戏,这里我将MainActivity设置成了横屏模式:

<activity android:name=".MainActivity" 
     android:screenOrientation="landscape">
  ...
</activity>

这样我们就实现类似于海岛奇兵和爱奇艺的沉浸式模式效果了,如下图所示。

 

可以看到,界面默认情况下是全屏的,状态栏和导航栏都不会显示。而当我们需要用到状态栏或导航栏时,只需要在屏幕顶部向下拉,或者在屏幕右侧向左拉,状态栏和导航栏就会显示出来,此时界面上任何元素的显示或大小都不会受影响。过一段时间后如果没有任何操作,状态栏和导航栏又会自动隐藏起来,重新回到全屏状态。

这就是最标准的沉浸式模式。

android 动态控制状态栏显示和隐藏的方法实例

android想要应用运行时全屏有一种方法是在activity的onCreat方法中加入如下代码:getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
并且需要在setContentView()之前,否则无效过。从这么多的苛刻条件可以看出这种方法无法满足动态控制。

下面的方法可以满足这个需要。调用View的 setSystemUiVisibility()

方法,其参数如下:

  1. View.SYSTEM_UI_FLAG_FULLSCREEN, //全屏,状态栏和导航栏不显示
  2. View.SYSTEM_UI_FLAG_HIDE_NAVIGATION, //隐藏导航栏
  3. View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, //全屏,状态栏会盖在布局上
  4. View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
  5. View.SYSTEM_UI_FLAG_LAYOUT_STABLE,
  6. View.SYSTEM_UI_FLAG_LOW_PROFILE,
  7. View.SYSTEM_UI_FLAG_VISIBLE, //显示状态栏和导航栏
  8. View.SYSTEM_UI_LAYOUT_FLAGS

Android colorPrimary colorPrimaryDark colorAccent

Android design theme color

<style name="AppTheme.NoActionBar">
  <!--状态栏颜色-->
  <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
  <!--控制各个控件被选中时的颜色-->
  <item name="colorAccent">@color/colorAccent</item>
  <!--页面背景色-->
  <item name="android:windowBackground">@color/windowBackg</item>
  <!--底部导航栏颜色-->
  <item name="android:navigationBarColor">@color/navigationColor</item>
  <!--Appbar背景色-->
  <item name="android:colorPrimary">@color/colorPrimary</item>
  <!--ToolBar上的Title颜色-->
  <item name="android:textColorPrimary">@color/textColorPrimary</item>
  <!--各个控制控件的默认颜色-->
  <item name="android:colorControlNormal">@color/colorControlNormal</item>
</style>

 

Android design theme color 保存在res/values/styles.xml下

<resources>

  <!-- Base application theme. -->
  <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
  </style>

</resources>

color rgb值保存在res/values/colors.xml下

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <color name="colorPrimary">#3F51B5</color>
  <color name="colorPrimaryDark">#000000</color>
  <color name="colorAccent">#ffffff</color>
</resources>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# android  # 隐藏状态栏  # android动态隐藏控件  # android沉浸式状态栏  # Android 状态栏的设置适配问题详解  # Android系统更改状态栏字体颜色  # android 动态控制状态栏显示和隐藏的方法实例  # Android 去掉状态栏的方法汇总  # Android应用图标在状态栏上显示实现原理  # 3种Android隐藏顶部状态栏及标题栏的方法  # Android自定义状态栏颜色与应用标题栏颜色一致  # Android实现修改状态栏背景、字体和图标颜色的方法  # Android 实现沉浸式状态栏的方法  # Android状态栏的适配汇总  # 状态栏  # 全屏  # 所示  # 都是  # 饿了  # 如下图  # 就可以  # 会让  # 可以看到  # 使用了  # 设置成  # 左拉  # 只需要  # 玩游戏  # 类似于  # 到底是什么  # 不叫  # 需要注意  # 如何实现  # 差得 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel如何为API生成Swagger或OpenAPI文档  laravel怎么用DB facade执行原生SQL查询_laravel DB facade原生SQL执行方法  免费的流程图制作网站有哪些,2025年教师初级职称申报网上流程?  iOS验证手机号的正则表达式  Laravel怎么发送邮件_Laravel Mail类SMTP配置教程  香港服务器建站指南:外贸独立站搭建与跨境电商配置流程  手机网站制作与建设方案,手机网站如何建设?  标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析  jimdo怎样用html5做选项卡_jimdo选项卡html5实现与切换效果【指南】  高防服务器租用首荐平台,企业级优惠套餐快速部署  详解Nginx + Tomcat 反向代理 如何在高效的在一台服务器部署多个站点  详解MySQL数据库的安装与密码配置  Laravel如何生成URL和重定向?(路由助手函数)  为什么要用作用域操作符_php中访问类常量与静态属性的优势【解答】  Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程  使用spring连接及操作mongodb3.0实例  laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法  Mybatis 中的insertOrUpdate操作  Laravel Admin后台管理框架推荐_Laravel快速开发后台工具  如何快速搭建支持数据库操作的智能建站平台?  如何挑选最适合建站的高性能VPS主机?  Claude怎样写约束型提示词_Claude约束提示词写法【教程】  哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?  成都网站制作公司哪家好,四川省职工服务网是做什么用?  如何快速查询域名建站关键信息?  Laravel如何实现数据导出到CSV文件_Laravel原生流式输出大数据量CSV【方案】  如何用5美元大硬盘VPS安全高效搭建个人网站?  Android利用动画实现背景逐渐变暗  百度输入法ai组件怎么删除 百度输入法ai组件移除工具  Laravel如何发送系统通知?(Notification渠道示例)  如何快速生成橙子建站落地页链接?  如何快速生成凡客建站的专业级图册?  Laravel如何处理文件下载请求?(Response示例)  详解jQuery中的事件  公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?  Laravel如何实现数据导出到PDF_Laravel使用snappy生成网页快照PDF【方案】  历史网站制作软件,华为如何找回被删除的网站?  Laravel怎么调用外部API_Laravel Http Client客户端使用  制作企业网站建设方案,怎样建设一个公司网站?  Laravel怎么实现API接口鉴权_Laravel Sanctum令牌生成与请求验证【教程】  Laravel如何使用Service Provider注册服务_Laravel服务提供者配置与加载  如何快速查询网址的建站时间与历史轨迹?  如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?  韩国网站服务器搭建指南:VPS选购、域名解析与DNS配置推荐  如何快速完成中国万网建站详细流程?  关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)  Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】  在线ppt制作网站有哪些软件,如何把网页的内容做成ppt?  js实现获取鼠标当前的位置  Java解压缩zip - 解压缩多个文件或文件夹实例