Android 状态栏透明

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 状态栏透明相关的知识,希望对你有一定的参考价值。

参考技术A

前言:最近项目大量用到状态栏透明,网上也出现很多库可以直接拿来用,个人认为没有必要那么重引用到一个库(有木有同学和我有一样的想法),所以研究了一番,在此做个记录加强记忆也便后期查阅,如果无意中有幸能帮助到你那就再好不过了。

android 从 4.4 (SDK 19) 开始支持 系统栏(状态栏+导航栏)半透明 效果:

翻译一下就是:

TranslucentDecor 主题设置了两个属性 windowTranslucentStatus 和 windowTranslucentNavigation 都为 true,前者指定状态栏半透明、后者指定导航栏半透明。

本文只探讨“状态栏”

默认样式是这样:

可见 Toolbar 和系统状态栏之间有明显的分界,我们要实现的效果是 Toolbar 和状态栏背景统一,看起来像是一个整体(自行脑补图片)。

按照官方文档,我们自定义主题:

对应的 Activity 引用该主题:

我看来看看效果:

虽然实现了半透明,但是布局被状态栏覆盖,接下来在布局文件中设置 fitSystemWindows (注意加到根节点 ConstraintLayout 上):

来看看效果:

虽然布局没有被状态栏覆盖,但是状态栏背景显然这不是我们想要的效果😭

为什么状态栏会这么奇怪?

文章开头的定义中我们说了,布局文件会延伸到状态栏所占区域下, fitsSystemWindows 的作用是给对应的 View 增加 padding(这里以 ConstraintLayout 为例),目的是为了让其内容不被状态栏遮挡。

在我们的布局文件中 ConstraintLayout 没有设置背景(默认白色),所以状态栏默认的半透明背景色和 ConstraintLayout 的白色背景叠加,就变成了上图中的效果。

【总结】两个基本概念:

1、 windowTranslucentStatus 设置为true之后,状态栏默认是 半透明 的(4.4 是黑色到透明色渐变,5.0+ 是纯黑色半透明),和我们要求的 透明 相去甚远。更重要的是,布局会延伸到状态栏底下。

2、 android:fitsSystemWindows 简单理解 就是 View 为了适配系统状态栏和导航栏(不被遮挡)自动 增加 padding ,当然真正的实现原理比这复杂很多而且不同的 View 可以自定义实现方式。

所以,为了实现文章开头提出来的“状态栏透明”效果,我们需要处理:

设置 windowTranslucentStatus 为 true,让状态栏半透明。

在根节点设置 android:fitsSystemWindows 使其不被状态栏遮挡。

Android 4.4 暂时没有办法去掉状态栏的渐变。

Android 5.0+ 开始支持修改状态栏颜色,设置透明色即可把半透明去掉。

看看效果:

我们看到即使状态栏透明了,但是其底色是一片白,因为跟节点 ConstraintLayout 没有设置背景,大多情况下我们不会给整个跟节点设置颜色,可以考虑把 android:fitsSystemWindows 设置到子 View 上,本例中是 AppBarLayout (5.0+ 无效,只能显式给 AppBarLayout 加 padding,可以利用其背景色),实际项目中可灵活调整。

最终效果:

至此,完成状态栏透明效果,网上有很多库,实际上都是基于此原理,在此基础上再自定义 View 做为状态栏背景。

https://developer.android.com/about/versions/android-4.4.html

android沉浸式状态栏变色状态栏透明状态栏修改状态栏颜色及透明

首先我要区分清楚沉浸式状态栏与变色状态栏。

沉浸式状态栏指的是,状态栏隐藏,在手指做了相关操作后,状态栏显示出来,例如视频播放器,在播放视频时是隐藏状态栏的,但是点击屏幕的时候,状态栏会显示出来,再例如文本阅读器,在阅读的时候是全屏的,然后从屏幕上方下滑或者下方上划,虚拟键和状态栏出现了,但却是直接覆盖在程序文字上的,这是所谓的沉浸式状态栏。
那么大家平时所说的状态栏与导航栏颜色相同,或者透明,指的是变色状态栏,或者透明状态栏。
对于这两个概念的理解,大家可以参考http://www.androidchina.net/3520.html

v19(4.4)以后开始支持android:windowTranslucentStatus属性,透明状态栏,而v21(5.0)以后出现变色状态栏,可以自由设置状态栏颜色。
通过这两个新特性,可以帮助我们快速的实现4.4以后的状态栏与app的导航栏颜色相同。

实现变色导航栏主要是通过styles里面的theme来实现的:

<resources>

    <style name="AppTheme.Base" parent="Theme.AppCompat.Light">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

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

首先,在 “values\\styles.xml” 中定义一个最基础的theme,AppTheme.Base,该主题继承于AppCompat.Light主题,因为本例子中使用了toolbar(谷歌已经建议用toolbar取代actionbar),因此该主题的主要目的是用于隐藏自带的actionBar,以及设置不显示title。

<style name="AppTheme.Base" parent="Theme.AppCompat.Light">
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
</style>

接下来定义主题BaseAppTheme,继承于上面定义的AppTheme.Base主题,该主题定义了三个颜色,分别指定状态栏、toolbar和页面中重点控件的颜色(颜色自己去定义)。

<style name="BaseAppTheme" parent="AppTheme.Base">
    <item name="colorPrimary">@color/colorPrimary</item>    <!-- 状态栏 -->
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <!-- toolbar -->
    <item name="colorAccent">@color/colorAccent</item>  <!-- 重点 -->
</style>

对于AppCompat主题中,各个颜色属性的含义,可以参考下图

这里写图片描述

然后定义一个AppTheme,继承于BaseAppTheme,

<style name="AppTheme" parent="BaseAppTheme"/>

在AndroidManifest.xml里application标签下设置主题 android:theme="@style/AppTheme"

到此,对于4.4以下的系统,会使用values\\styles.xml中的AppTheme主题,那么在4.4跟5.0这两个系统下,我们要做以下的处理。

4.4:新建“values-v19\\styles.xml”

在里面定义适用与4.4系统的AppTheme,在4.4系统中提出的是透明状态栏,因此这里我们定义一个AppTheme继承于BaseAppTheme,其中只要实现透明状态栏,代码如下:

<style name="AppTheme" parent="BaseAppTheme">
    <item name="android:windowTranslucentStatus">true</item>
</style>

5.0:新建“values-v21\\styles.xml”

在里面定义适用与5.0系统的AppTheme,在5.0系统中提出的变色状态栏,因此这里我们只需定义一个AppTheme继承于BaseAppTheme代码如下:

<style name="AppTheme" parent="BaseAppTheme"/>

注意在布局文件中要设置如下属性,根据其字面意思,理解为,是否适应系统窗口,当设为true的时候,适应系统窗口,布局时会考虑状态栏的存在;如果设为false,则不考虑状态栏的存在,全屏显示,状态栏出现在布局上层,可参考下面效果图。
android:fitsSystemWindows=”true”

设为true:
这里写图片描述

设为false:
这里写图片描述

完成以上设置以后,就可以达到在4.4系统以上自定义状态栏、导航栏等颜色的目的。

状态栏透明

上面研究的是状态栏与导航栏颜色的设置,那么如何实现上图所示的,状态栏、导航栏透明,背景图片全屏显示的呢?
按道理想,既然可以设导航栏的颜色,那么我直接把颜色设成透明色,是不是就可以了呢?
答案是,正解~

不过,还是要处理一些特殊情况。

首先,我们把styles中的颜色设为透明,然后在主页面根布局下,设置一个背景图和设置 android:fitsSystemWindows=”true” 属性

<style name="BaseAppTheme" parent="AppTheme.Base">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/transparence</item>    <!-- 状态栏 -->
    <item name="colorPrimaryDark">@color/transparence</item> <!-- toolbar -->
    <item name="colorAccent">@color/colorAccent</item>  <!-- 重点 -->
</style>

运行的结果是,在4.4系统上,完全正常显示,而在5.0上,toolbar正常显示了透明色,但是状态栏显示的是灰色透明色
4.4系统:
这里写图片描述

5.0系统:
这里写图片描述
原因应该是,4.4系统支持的就是透明状态栏,所以只需要将状态栏颜色设为透明,即可到达效果。
而5.0支持的是变色状态栏,得到的效果与我们预期不同,特做如下处理:

在代码中设置,判断当sdk大于等于5.0时,执行以下代码

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    Window window = getWindow();
    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    window.setStatusBarColor(Color.TRANSPARENT);
}

运行后,在4.4以及5.0系统上都能实现透明效果了,效果图如下:
这里写图片描述

源码下载

以上是关于Android 状态栏透明的主要内容,如果未能解决你的问题,请参考以下文章

android 透明状态栏是怎样实现的

android沉浸式状态栏变色状态栏透明状态栏修改状态栏颜色及透明

android为啥透明不能全屏?如何将状态栏给隐藏起来。

Android 隐藏状态栏、标题栏、透明状态栏的几种方式

Android 透明状态栏&着色状态栏

Android 透明状态栏