首页 > 代码库 > 系统栏系列之背景图片侵入系统栏

系统栏系列之背景图片侵入系统栏

实现效果

1. 只有4.4系统及之后才具有应用内容背景侵入状态栏效果;

2. 没有ActionBar/Toolbar;

3. 4.4系统手机上,不能实现全透明效果,状态栏带有渐变的灰色半透明色。

4. 5.0系统以上手机,可实现状态栏全透明效果。

Android 4.4 的新特性之半透明系统栏

我们可以利用4.4系统提供的windowTranslucentNavigationwindowTranslucentStatus 两个属性,在自定义的主题中设置为true,实现系统栏的一个半透明的过渡保护色(防止是白色背景侵入到系统栏,使得系统栏显示信息看不清)的显示效果,此时应用的内容布局填冲状态栏和系统栏背后的部分,但是系统栏后面的内容布局是不能响应事件的,比如点击顶部的状态栏时,状态栏后面的控件是不会响应时间,点击底部导航栏相应的是导航栏响应事件。

因此这可以作为一种全屏化背景显示的效果(没有Actionbar/Toolbar)。

实现代码
在res/values-v19/styles.xml加入这两个渐变属性,如果系统最小支持版本小于4.4则需要建立values-v19文件夹做适配,不然会提出出错。在对应的Activity中引入此主题即可。这样就会在4.4以上系统出现此效果。图片是设置在activity的根布局中做背景的。

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
      <item name="android:windowTranslucentStatus">true</item>
      <item name="android:windowTranslucentNavigation">true</item>
    </style>
</resources>

将此主题在清单文件中设置到对应的activity中,4.4系统手机上实现效果如下:
技术分享

那么在4.4以上的系统,即5.0及之后的系统中是什么效果呢?
技术分享
可以看到是淡灰色透明的保护色,亲测5.1/6.0系统手机均如此。

不过最好是不要对底部的导航栏做操作,有些手机没有下面一排实体按键,而且会影响与导航栏后面的View与用户的交互。因此我们删除
<item name="android:windowTranslucentNavigation">true</item>

Android5.0 的Material Design中实现5.0及以上的全透明状态栏效果

Android 5.0的Material Design提供了statusBarColor来动态设置状态栏的颜色,因此是否可以在5.0及以上系统手机上实现彻底的透明的状态栏效果呢?我们先在res文件夹下创建用于5.0及以上系统用的values-v21文件夹,并在此目录下新建文件styles.xml,以下操作都在此文件中修改。
1. 第一次尝试:windowTranslucentStatus+statusBarColor
通过statusBarColor设置为透明,强制将状态栏的半透明淡灰保护色给去掉。

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowTranslucentStatus">true</item>
       <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
</resources>

显示效果如下:
技术分享
结果然并卵了,没有效果。
2.第二次尝试:只用statusBarColor属性,删除windowTranslucentStatus属性,怎么样?

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
       <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
</resources>

技术分享
状态栏一片空白。Pass
3.第三尝试:
终于在简书的D_clock爱吃葱花的《Android开发:Translucent System Bar 的最佳实践》中找到一个实现方案。

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowTranslucentStatus">false</item>
        <item name="android:windowTranslucentNavigation">true</item>
       <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
</resources>

效果如下:
技术分享
很被动的就达到了全透明的效果。
4.当然还是不能忍的,直接AndoriDev找android:statusBarColor介绍
在Material Design中我找到了Window.setStatusBarColor() 的介绍:

setStatusBarColor
Added in API level 21
Sets the color of the status bar to color. For this to take effect, the window must be drawing the system bar backgrounds with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS and FLAG_TRANSLUCENT_STATUS must not be set.
If color is not opaque, consider setting SYSTEM_UI_FLAG_LAYOUT_STABLE and
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN.

简单解说下,这个方法是用于为状态栏设置颜色的,为了让设置的颜色起作用,它必须和FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS连用,并且不能设置FLAG_TRANSLUCENT_STATUS;如果是透明色,则需要与SYSTEM_UI_FLAG_LAYOUT_STABLESYSTEM_UI_FLAG_LAYOUT_FULLSCREEN连用。
看到没赤裸裸的打脸,4.4的FLAG_TRANSLUCENT_STATUS和5.0的android:statusBarColor是不能连用的,从二者作用上理解,前者是实现透明状态栏,并使得应用内容侵入到状态栏之后,而后者这要作用是用于设置颜色,是相冲突的。因此4.4是FLAG_TRANSLUCENT_STATUS是一个复合作用标签,但是它不完美,它还提供了系统栏的保护色。

那么,我们需要使用后两个标签,但是在AppTheme中是找不到这两个属性进行设置的。

它们是在Android 4.1之后加入的用于将应用内容显示在系统栏之后的标记,此标记只用于View的setSystemUiVisibility()方法中:SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN用于将应用内容显示在状态栏之后,对应的也就有SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION标签,作用于导航栏之后。而SYSTEM_UI_FLAG_LAYOUT_STABLE这个标志来帮助应用维持一个稳定的布局。他们的出现是与4.1的隐藏系统栏一同出现的,用于稳定布局,使得在系统栏隐藏和出现的过程中内容布局不会发生大小的改变时的突兀感。

从此可知在5.0及之后的系统中,通过5.0的设置状态栏颜色标签和4.1具有侵入状态栏的布局标签,结合使用获得所需要的效果,而且没有保护色的副作用。

public class UniformBackgroundActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_uniform_background);
        getWindow().getDecorView().setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | 
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE );
    }
}

技术分享
技术分享

代码总结:

1、创建res/values-v19/styles.xml文件,加入如下代码:

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
      <item name="android:windowTranslucentStatus">true</item>
      <!-- 如果需要导航栏也透明加下面这行代码 -->
      <item name="android:windowTranslucentNavigation">true</item>
    </style>
</resources>

2、创建res/values-v21/styles.xml文件,加入如下代码

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:statusBarColor">@android:color/transparent</item>
        <!-- 如果需要导航栏也透明加下面这行代码 -->
        <item name="android:navigationBarColor">@android:color/transparent</item>
    </style>
</resources>

3.在Activity的onCreate方法中加入如下代码:

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
           //如果需要透明导航栏,请加入标记
           //View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            getWindow().getDecorView().setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
                            View.SYSTEM_UI_FLAG_LAYOUT_STABLE );
        }

4.清单文件中为此activity添加Theme属性

<activity android:name=".xxxActivity"
            android:theme="@style/AppTheme"
            ></activity>
<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

    系统栏系列之背景图片侵入系统栏