封面.png

一、前言

其实我是不打算写这篇文章的,为什么呢?因为关于沉浸式状态栏的文章太多了,随便google一下就能出来几十上百篇文章,当然这其中有写的好的,也有滥竽充数的。前面在公众号推出了Material Design 的系列文章,就有读者留言,希望出一篇关于沉浸式的文章。因此这篇文章就整理总结一下各个版本的实现原理,顺便为大家推荐一个我觉得很方便的一个库。

二、沉浸式的一般套路

在介绍这个方便的轮子之前,我们先一起来回顾一下实现沉浸式状态栏的一般套路。在Android上,关于对StatusBar(状态栏)的操作,一直都在不断改善,并且表现越来越好,在Android4.4 以下,我们可以对StatusBar和 NavigationBar进行显示和隐藏操作。但是直到Android4.4,我们才能真正意义上的实现沉浸式状态栏。从Android4.4 到现在(Android 7.1),关于沉浸式大概可以分成三个阶段:

Android4.4(API 19) - Android 5.0(API 21): 这个阶段可以实现沉浸式,但是表现得还不是很好,实现方式为: 通过FLAG_TRANSLUCENT_STATUS设置状态栏为透明并且为全屏模式,然后通过添加一个与StatusBar 一样大小的View,将View 的 background 设置为我们想要的颜色,从而来实现沉浸式。

Android 5.0(API 21)以上版本: 在Android 5.0的时候,加入了一个重要的属性和方法 android:statusBarColor (对应方法为 setStatusBarColor),通过这个方法我们就可以轻松实现沉浸式。也就是说,从Android5.0开始,系统才真正的支持沉浸式。

Android 6.0(API 23)以上版本:其实Android6.0以上的实现方式和Android 5.0 +是一样,为什么要将它归为一个单独重要的阶段呢?是因为从Android 6.0(API 23)开始,我们可以改状态栏的绘制模式,可以显示白色或浅黑色的内容和图标(除了魅族手机,魅族自家有做源码更改,6.0以下就能实现)

大概就是这个三个阶段,那么接下来我们就看一下这个三个阶段分别是如何来实现的。

2.1 Android4.4(API 19) - Android 5.0(API 21)实现沉浸式的方式

Android 4.4 为什么能够实现沉浸式的效果呢?因为在Android 4.4 新增了一个重要的属性:FLAG_TRANSLUCENT_STATUS

/**

* Window flag: request a translucent status bar with minimal system-provided

* background protection.

*

*

This flag can be controlled in your theme through the

* {@link android.R.attr#windowTranslucentStatus} attribute; this attribute

* is automatically set for you in the standard translucent decor themes

* such as

* {@link android.R.style#Theme_Holo_NoActionBar_TranslucentDecor},

* {@link android.R.style#Theme_Holo_Light_NoActionBar_TranslucentDecor},

* {@link android.R.style#Theme_DeviceDefault_NoActionBar_TranslucentDecor}, and

* {@link android.R.style#Theme_DeviceDefault_Light_NoActionBar_TranslucentDecor}.

*

*

When this flag is enabled for a window, it automatically sets

* the system UI visibility flags {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} and

* {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.

*/

public static final int FLAG_TRANSLUCENT_STATUS = 0x04000000;

解释:设置状态栏透明,并且变为全屏模式。上面的解释已经说得很清楚了,当window的这个属性有效的时候,会自动设置 system ui visibility的标志SYSTEM_UI_FLAG_LAYOUT_STABLE和SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 。

有两种方式实现这个属性:

可以在代码中设置,如下:

activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

当然也可以在theme 中设置属性windowTranslucentStatus,如下:

android:windowTranslucentStatus

效果如下:

效果如上图,可以看出,沉浸式的效果是出来了,但是也有一个问题,我们的标题栏和状态栏重叠了,相当于整个布局上移了StatusBar 的高度。

为了让标题栏回到原来的位置,我们在标题栏的上方添加一个大小和StatusBar大小一样的View,View 的BackgroundColor 为标题栏一样的颜色,这个View起到一个占位的作用。这个时候,标题栏就会下移StatusBar的高度,回到正常的位置。

添加如下代码:

//获取windowphone下的decorView

ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();

int count = decorView.getChildCount();

//判断是否已经添加了statusBarView

if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {

decorView.getChildAt(count - 1).setBackgroundColor(calculateStatusColor(color, statusBarAlpha));

} else {

//新建一个和状态栏高宽的view

StatusBarView statusView = createStatusBarView(activity, color, statusBarAlpha);

decorView.addView(statusView);

}

ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);

//rootview不会为状态栏留出状态栏空间

ViewCompat.setFitsSystemWindows(rootView,true);

rootView.setClipToPadding(true);

创建和status bar 一样大小的View的代码如下:

private static StatusBarView createStatusBarView(Activity activity, int color, int alpha) {

// 绘制一个和状态栏一样高的矩形

StatusBarView statusBarView = new StatusBarView(activity);

LinearLayout.LayoutParams params =

new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));

statusBarView.setLayoutParams(params);

statusBarView.setBackgroundColor(calculateStatusColor(color, alpha));

return statusBarView;

}

其中StatusBarView 就是一个普通的View。

添加上述代码后,效果如下:

通过以上就可以实现Android 4.4 上的沉浸式状态栏。

另外,如果是一张图片延伸到状态栏的话,直接设置FLAG_TRANSLUCENT_STATUS就可以了,如下:

小结:Android4.4上实现沉浸式状态栏的套路是:为window添加FLAG_TRANSLUCENT_STATUS Flag,然后添加一个和status bar 一样大小的View 站位,从而让让标题栏不会与status bar 重叠。而图片延伸到状态栏只需要设置FLAG_TRANSLUCENT_STATUS就OK。

前面说过,沉浸式在Android4.4 - Android5.0 之间的版本表现得不是很好,从上面贴的几张图就可以看出,状态栏的顶部有一个渐变,会显示出黑色的阴影(底部的导航栏也是一样的效果),在Android 5.0 版本已经被修复了。

2.2 Android 5.0(API 21)以上实现沉浸式的方式

Android 5.0 是一个里程碑式的版本,从Android 5.0开始,Google 推出了全新的设计规范 Material Design,并且原生控件就可以实现一些炫酷的UI动效。从这个版本开始,google 加入了一个比较重要的方法setStatusBarColor (对应属性:android:statusBarColor),通过这个方法,可以很轻松地实现沉浸式状态栏。方法如下:

/**

* Sets the color of the status bar to {@code color}.

*

* For this to take effect,

* the window must be drawing the system bar backgrounds with

* {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} and

* {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS} must not be set.

*

* If {@code color} is not opaque, consider setting

* {@link android.view.View#SYSTEM_UI_FLAG_LAYOUT_STABLE} and

* {@link android.view.View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.

*

* The transitionName for the view background will be "android:status:background".

*

*/

public abstract void setStatusBarColor(@ColorInt int color);

注意看这个方法的注释,想要这个方法生效,必须还要配合一个Flag一起使用,必须设置FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS ,并且不能设置FLAG_TRANSLUCENT_STATUS(Android 4.4才用这个)

我们来看一下FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS这个flag:

可以看到,这个flag 也是在Android 5.0添加的,它的作用是什么呢?

解释:设置了FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,表明会Window负责系统bar的background 绘制,绘制透明背景的系统bar(状态栏和导航栏),然后用getStatusBarColor()和getNavigationBarColor()的颜色填充相应的区域。这就是Android 5.0 以上实现沉浸式导航栏的原理。

实现沉浸式添加如下代码:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

//注意要清除 FLAG_TRANSLUCENT_STATUS flag

getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

getWindow().setStatusBarColor(getResources().getColor(android.R.color.holo_red_light));

效果如下:

当然也可以直接在Theme中使用,在values-v21文件夹下添加如下主题:

false

true

@android:color/holo_red_light

效果和上面代码中添加的效果一样,这里就不贴效果图了。

图片延伸到状态栏

在Android 5.0 使图片延伸到状态栏,只需设置windowTranslucentStatus,将 statusBarColor 设置为透明即可:

true

true

@android:color/transparent

效果如下:

代码中通过版本号的判断兼容 Android5.0以下和Android 5.0以上:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

activity.getWindow().setStatusBarColor(calculateStatusColor(color, statusBarAlpha));

} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();

int count = decorView.getChildCount();

if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {

decorView.getChildAt(count - 1).setBackgroundColor(calculateStatusColor(color, statusBarAlpha));

} else {

StatusBarView statusView = createStatusBarView(activity, color, statusBarAlpha);

decorView.addView(statusView);

}

ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);

rootView.setFitsSystemWindows(true);

rootView.setClipToPadding(true);

setRootView(activity);

}

2.3 Android 6.0 + 实现状态栏字色和图标浅黑色

使用沉浸式的时候会遇到一个问题,那就是Android 系统状态栏的字色和图标颜色为白色,当我的主题色或者图片接近白色或者为浅色的时候,状态栏上的内容就看不清了。 ,这个问题在Android 6.0的时候得到了解决。Android 6.0 新添加了一个属性SYSTEM_UI_FLAG_LIGHT_STATUS_BAR

解释:为setSystemUiVisibility(int)方法添加的Flag,请求status bar 绘制模式,它可以兼容亮色背景的status bar 。要在设置了FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDSflag ,同时清除了FLAG_TRANSLUCENT_STATUSflag 才会生效。

添加如下代码:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

getWindow().getDecorView().setSystemUiVisibility(

View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);

}

效果如下:

除了在代码中添加以外,还可以直接在主题中使用属性:

false

true

@android:color/holo_red_light

true

注意:主题要放在values-v23文件夹下:

三、轮子StatusBarUtil

通过上面的介绍,其实将各个版本实现沉浸式的方式和原理都讲完了。但是或许当你真正去实践沉浸式状态栏的时候,你会感觉到无从下手,因此,我给大家推荐一个轮子StatusBarUtil,Github:https://github.com/laobie/StatusBarUtil。

为什么会推荐这个库呢?因为这个库就只有一个类StatusBarUtil,使用起来很方便,就像一个工具类一样使用。里面封装了很多静态方法,直接使用就好。自己添加也很方便。介绍一下使用的一些场景:

需要在setContentView()之后调用:

setContentView(R.layout.main_activity);

...

StatusBarUtil.setColor(MainActivity.this, mColor);

1,设置状态栏颜色

StatusBarUtil.setColor(Activity activity, int color)

2,设置状态栏半透明

StatusBarUtil.setTranslucent(Activity activity, int statusBarAlpha)

3,设置状态栏全透明

StatusBarUtil.setTransparent(Activity activity)

4,为包含 DrawerLayout 的界面设置状态栏颜色(也可以设置半透明和全透明)

StatusBarUtil.setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, int color)

5,为使用 ImageView 作为头部的界面设置状态栏透明(常用的场景为详情页的Header部分)

StatusBarUtil.setTranslucentForImageView(Activity activity, int statusBarAlpha, View needOffsetView)

6,在 Fragment 中使用

status_uti

四、最后

以上就是对于沉浸式状态栏的一些总结,希望可以给还没有使用沉浸式的同学一些帮助。如果你已经使用过沉浸式状态栏,也不仿看一下,可以对各个版本实现的原理有一个更深的了解。最后,推荐了一个不错的库,更确切的说,应该是一个不错的工具类。如有问题,欢迎交流。

android 状态栏占位_Android关于沉浸式状态栏的一些总结相关推荐

  1. android 工具栏沉浸 下拉,如何在Android应用中实现一个沉浸式状态栏效果

    如何在Android应用中实现一个沉浸式状态栏效果 发布时间:2020-12-08 17:04:42 来源:亿速云 阅读:151 作者:Leah 这篇文章将为大家详细讲解有关如何在Android应用中 ...

  2. android开发沉浸式标题栏_android实现沉浸式状态栏

    前言 在android开发的过程中,经常会涉及到沉浸式状态栏的问题,说白了,就是手机屏幕顶部栏的颜色显示问题,为了实现美感一体的效果,许多app都已经开始了沉浸式状态栏的显示,这里,我也简单介绍一个沉 ...

  3. android 9.0去掉状态栏,安卓9.0沉浸式状态栏

    首先我们来了解一下几个设置沉浸式状态栏的基础属性: 1.View.SYSTEM_UI_FLAG_LOW_PROFILE:低调模式, 会隐藏不重要的状态栏图标: 2.View.SYSTEM_UI_FLA ...

  4. Android开发之android4.4沉浸式状态栏后toolbar和状态栏重复(重叠,覆盖)的bug

    我们看下android4.4的手机沉浸式状态栏的效果图: 让所有的activity继承baseActivity,然后在baseactivity里面为重复的高度添加一个状态栏高度的view将toolba ...

  5. Android 系统(227)---沉浸式状态栏工具类

    沉浸式状态栏工具类 沉浸式状态栏的实现原理很简单,就是将状态栏隐藏掉,然后在原来状态栏的位置添加一个和状态栏大小一模一样的View,这个View的颜色定义成和Toolbar一样的颜色就行了 在styl ...

  6. Android 9.0 10.0 沉浸式状态栏导致导航栏状态栏灰色蒙层的解决方案

    1.概述 在10.0的系统产品开发中,在app开发中,沉浸式状态栏也是常有的样式,但是设置沉浸式状态栏后,会导致状态栏和导航栏会有灰色蒙层的问题存在 解决方案: DecorView是整个Window界 ...

  7. java沉浸状态栏代码,Ionic实现沉浸式状态栏,状态栏与APP融为一体

    在新的项目中,我按照需求需要设计沉浸式状态栏,当然一开始我还不知道这个叫做"沉浸式状态栏",到网上搜索半天都找不到结果.我搜索了"Ionic刘海屏自适应",&q ...

  8. Android 隐藏虚拟按键和沉浸式状态栏

    private void hideNavigationBar() {Window window = this.getWindow();window.setFlags(WindowManager.Lay ...

  9. 沉浸式状态栏需要写html,沉浸式状态栏

    android Api21之后的状态栏会默认覆盖半透明遮罩,我们需要新建values-19,values-21 2份styles文件进行适配 Api-19 true true Api-21 false ...

最新文章

  1. linux之sort 命令详解
  2. gradle插件用户指南(翻译)
  3. 2022年全球及中国面粉加工机械行业竞争现状与发展前景规模分析报告
  4. AI理论知识整理(2)-对称矩阵-特征值与特征向量
  5. ASP.NET学习笔记 2
  6. 【渝粤题库】广东开放大学 外贸会计1 形成性考核
  7. [css] 用css画一个太阳
  8. python3.5.2使用教程_Python3.5.2-初级教程.docx
  9. 设计模式(一)单例模式:5-单元素枚举类模式
  10. Android开源项目推荐之「网络请求哪家强」
  11. 成为Android高手的十个建议
  12. paip.java 线程无限wait的解决
  13. 手把手带你玩转Spark机器学习-Spark的安装及使用
  14. 乐优购物学习笔记(5)
  15. 使用vue-cropper
  16. 计算机模拟地球爆炸,地球爆炸模拟器最新版
  17. bootstrap 检验 法 原理_Stata:刀切法/留一法/Jackknife 简介
  18. jquery图片放大镜插件—jqzoom
  19. Unable to negotiate with XXXX port 22: no matching host key type found. Their offer: ssh-rsa,ssh-dss
  20. php中脚本代码开始,从PHP代码中执行shell脚本

热门文章

  1. 五月集训——Day4:1400
  2. 百度地图开发系列(5):高亮显示省市县级别的行政区域
  3. 陕西计算机三本院校排名,陕西三本院校排名文科
  4. 天线基础知识(二)天线角度
  5. 09 编译2022年最新的Linux kernel、U-Boot和BusyBox rootfs源码,并用QEMU模拟器运行
  6. 带你轻松看懂机器学习工作流——以“点一份披萨外卖”为例
  7. 鱼c工作室python-鱼C工作室Python作业
  8. GNSS高边坡在线监测预警系统解决方案
  9. Java校验身份证号工具类
  10. 家到学校路线图怎么画_我家到学校的地图 地图简笔画大全