Android沉浸式状态栏(透明状态栏)最佳实现


在Android4.4之前,我们的应用没法改变手机的状态栏颜色,当我们打开应用时,会出现上图中左侧的画面,在屏幕的顶部有一条黑色的状态栏,和应用的风格非常不协调;为了提供更好的界面交互,google在Android4.4以后提供了设置沉浸式状态栏的方法,对于沉浸式状态栏这个名字存在争议,我们不做讨论,实际的效果其实就是透明的状态栏,然后在状态栏的位置显示我们自定义的颜色,通常为应用的actionbar的颜色,或者是将应用的整体的一张图片也占据到状态栏中,如下图所示:

由于这种透明的状态栏是在Android4.4以后才出现的,所以我们需要为4.4以上的版本做适配,方法有两种,一种是在资源文件(style)中设置,一个是在代码中设置。

在资源文件中设置透明状态栏

首先,我们先在values下的style中加入如下代码:

  1. <!-- Base application theme. -->
  2. <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
  3. <!-- Customize your theme here. -->
  4. <item name="colorPrimary">@color/colorPrimary</item>
  5. <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
  6. <item name="colorAccent">@color/colorAccent</item>
  7. </style>
  8. <style name="AppTheme.Main" parent="AppTheme" />
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

AppTheme.Main是我们要设置给activity的主题,它应该继承于AppTheme.NoActionBar,然后
我们在values-v19中加入同样的AppTheme.Main,如下所示:

  1. <style name="AppTheme.Main" parent="AppTheme.NoActionBar">
  2. <item name="android:windowTranslucentStatus">true</item>
  3. </style>
  • 1
  • 2
  • 3

然后运行程序,效果如图所示:

图片中我们发现,虽然我们实现了透明的状态栏,但是上边的文字和状态栏的信息重叠了。为了修复这个问题,我们应该在布局文件的根布局中加入android:fitsSystemWindows=”true” 就可以了,加入后效果如下:

应用的文字和系统显示的文字错开了,这也是我们最终的显示效果

需要注意的几点:

  1. 为Android4.4+适配的同时,不要忘了在values的style.xml中加入同名的自定义style,不然4.4以下会报错
  2. 不要忘记在布局文件中加入 android:fitsSystemWindows=”true”,不然布局内容会和状态栏内容重叠
  3. 在Android5.0中,透明标题的效果和4.4中有所不同,但是实现方法相同,我们可以不必为5.0+单独适配,同时5.0+的版本提供了新的API

    android:statusBarColor,可以用来单独设置状态栏的颜色,但是这种方法不适用于我们例子中的图片占据状态栏,它适用于纯色的状态栏,并且它应该放到value-v21文件夹中

    上边的例子中,我们只设置了一个图片,使其占据了状态栏。但是我们平常见到更多的可能不是这种,而且带actionbar的情况,如下所示:

    在上图中,存在一个actionbar,然后状态栏的颜色与其相同,接下来我们来实现这种效果。

style文件不用改变,我们需要在布局文件中加入一个toolbar,代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. xmlns:app="http://schemas.android.com/apk/res-auto"
  5. xmlns:tools="http://schemas.android.com/tools"
  6. android:layout_width="match_parent"
  7. android:layout_height="match_parent"
  8. android:background="@color/colorAccent"
  9. android:orientation="vertical"
  10. tools:context="com.zephyr.musicapp.MainActivity">
  11. <android.support.v7.widget.Toolbar
  12. android:id="@+id/toolbar"
  13. android:layout_width="match_parent"
  14. android:layout_height="wrap_content"
  15. android:fitsSystemWindows="true"
  16. android:background="?attr/colorPrimary"
  17. app:popupTheme="@style/AppTheme.PopupOverlay"/>
  18. </LinearLayout>
  19. 然后在activity中
  20. Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
  21. setSupportActionBar(toolbar);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

在一个LinearLayout中包含了一个toolbar,和第一个例子相比,我们把android:fitsSystemWindows=”true”加在了Toolbar上边,而不是LinearLayout中,如果把android:fitsSystemWindows=”true”放到LinearLayout中,会出现下边的效果:

虽然状态栏透明了,但是颜色却和根布局的颜色相同而不是toolbar,这样显然不行,如果我们把android:fitsSystemWindows=”true”放到toolbar中就可以实现我们的效果,如下图所示:

在这里,我们还需要特别注意一个地方,那就是在设置toolbar高度的时候,应该设置成wrap_content,不然也没法实现我们的效果,比如我把高度固定为50dp,效果如下:

虽然占据了状态栏,但是toolbar的高度明显不够了,效果很不好。

在Android5.0以后,增加了新的API android:statusBarColor
用于设置状态栏的颜色,同时以前的windowTranslucentStatus也是对它有效的,所以如果想通过新的API设置状态栏颜色的话,首先应该将windowTranslucentStatus设置为false,不然是没有效果的。

以上就是通过资源文件设置透明状态栏的方法。

代码中设置透明状态栏

在代码中设置透明状态栏的方法也很简单,思路就是首先通过
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS设置当前window为透明状态栏,这样标题栏就可以占据状态栏了,但是会出现布局中的内容和状态栏的内容重叠的问题,为了解决这个问题,我们应该获得状态栏的高度,然后设置标题栏的paddingTop为状态栏的高度,这样就可以实现透明效果的标题栏的,代码如下:

  1. protected void setImmerseLayout(View view) {// view为标题栏
  2. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  3. Window window = getWindow();
  4. window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  5. int statusBarHeight = getStatusBarHeight(this.getBaseContext());
  6. view.setPadding(0, statusBarHeight, 0, 0);
  7. }
  8. }
  9. public int getStatusBarHeight(Context context) {
  10. int result = 0;
  11. int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen",
  12. "android");
  13. if (resourceId > 0) {
  14. result = context.getResources().getDimensionPixelSize(resourceId);
  15. }
  16. return result;
  17. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

fitSystemWindows属性:
官方描述:
Boolean internal attribute to adjust view layout based on system windows
such as the status bar. If true, adjusts the padding of this view to
leave space for the system windows. Will only take effect if this view
is in a non-embedded activity.


补充:
当为纯色actionbar的情况下,我们将toolbar的高度设为wrap_content,并且将fitsSystemWindows=“true”参数设置到了toolbar上,这样虽然实现了4.4版本的沉浸效果,但是却不能有效的适配5.0及以上的版本,所以做出以上修改。

在4.4版本上:
1. 我们将根布局的背景颜色设置成和toolbar一样的,并且设fitsSystemWindows为true。
2. toolbar的fitsSystemWindows属性去掉,并且高度设置为?attr/actionBarSize
3. 在toolbar下增加一个子布局,颜色设置为white,这样就可以在4.4及5.0以上实现带actionbar的沉浸式布局

2017.12.14更新:
使用纯色actionbar的时候,可以使用容器包裹toolbar,只设置容器
fitsSystemWindows为true。由于fitsSystemWindows属性本质上是给当前控件设置了一个padding,所以我们设置到根布局的话,会导致状态栏是透明的,并且和窗口背景一样,和toolbar背景不同。如果我们设置给toolbar,则会由于padding的存在,导致toolbar的内容下移。所以我们选择使用LinearLayout包裹toolbar,并将toolbar的背景等属性设置在appbarlayout上就可以完美实现效果,代码:

  1. <LinearLayout
  2. android:layout_width="match_parent"
  3. android:layout_height="wrap_content"
  4. android:background="@color/colorPrimary"
  5. android:fitsSystemWindows="true"
  6. android:orientation="vertical">
  7. <android.support.v7.widget.Toolbar
  8. android:layout_width="match_parent"
  9. android:layout_height="?attr/actionBarSize"
  10. app:title="Login"/>
  11. </LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zephyr_g/article/details/53489320

Android沉浸式状态栏(透明状态栏)最佳实现的更多相关文章

  1. Android沉浸式(侵入式)标题栏(状态栏)Status(三)

     Android沉浸式(侵入式)标题栏(状态栏)Status(三) 从附录文章1,2可以看到,依靠Android系统提供的标准方案,状态栏即便在透明状态下,仍然有些半透明而不是全透明.本文是And ...

  2. android 沉浸式状态栏的实现

    本文介绍一种简单的实现沉浸式状态栏的方法,要高于或等于api19才可以. 实现android沉浸式状态栏很简单,添加代码两步就可以搞定. 一.在activity中添加 getWindow().addF ...

  3. [置顶] Xamarin android沉浸式状态栏

    虽然关于android "沉浸式"状态栏有很多博客介绍过,从小菜到大神无一例外.我第一次看到这种"沉浸"式的效果我也以为真的是这么叫,然而根本不是这么回事,完全 ...

  4. Android 沉浸式状态栏完美解决方案

    现在搜索Android 沉浸式状态栏,真的是一堆一堆,写的特别多,但是真正用的舒服的真没有,在这里自己整理一下开发记录 注意,在使用这个步骤过程之前,请把之前设置的代码注释一下 把布局带有androi ...

  5. 【Android实战】Android沉浸式状态栏实现(下)

    之前的Android沉浸式状态栏实现并没有考虑软键盘的影响,接下来的内容将会针对这个问题给出解决方式,先看一下效果图 这个是一个留言板的效果图: 即弹出软键盘的时候并不会导致整个布局上移. 详细怎样实 ...

  6. Android 沉浸式状态栏 实现方式二 ( 更简单 )

    以前写过一个沉浸式状态栏 的实现方式 Android 沉浸式状态栏 实现方式一 现在有个更为简单的实现方式 . 相关链接 http://www.apkbus.com/forum.php?mod=vie ...

  7. Android沉浸式(侵入式)标题栏(状态栏)Status(二)

     Android沉浸式(侵入式)标题栏(状态栏)Status(二) 附录1以xml写style实现了Android沉浸式(侵入式)状态栏(标题栏),同样以上层Java代码实现.在附录文章1的基础上 ...

  8. Android沉浸式(侵入式)标题栏(状态栏)Status(一)

     Android沉浸式(侵入式)标题栏(状态栏)Status(一) 现在越来越多的APP设计采用这种称之为沉浸式状态栏(Status)的设计,这种沉浸式状态栏又称之"侵入式"状 ...

  9. flutter android沉浸式状态栏

    import 'package:flutter/services.dart'; import 'dart:io'; class _MyAppState extends State<MyApp&g ...

随机推荐

  1. js作用域的几个问题

    按照<权威指南>的说法,全局的变量作用域是全局性的,在js代码中,他处处都有定义.而在函数之内声明的变量,就只有在函数体内有定义了.函数的参数也是局部变量,他们只在函数体内部有定义.在函数 ...

  2. 【shell】通过shell编写ping包及arp的监控并发送短信

    1 #!/bin/bash 2 NOW="`date +%Y%m%d-%H:%M:%S`" 3 PHONES=15134567893 4 IP=10.100.8.78 5 GATE ...

  3. HDU 5242 利用树链剖分思想进行贪心

    题目大意: 在给定带权值节点的树上从1开始不回头走到某个底端点后得到所有经过的点的权值后,这些点权值修改为0,到达底部后重新回到1,继续走,问走k次,最多能得到多少权值之和 这其实就是相当于每一次都走 ...

  4. POJ 1724 二维费用最短路

    题目大意:有N个城市,编号1-N有R条路,每条路(单向)的起点为Si,终点为Di,长度为Li,如果要走这条路需要花Ti的钱现在你只有K元钱,求在不超支的前提下,从1走到N需要的最短距离 这里总是希望路 ...

  5. 【思维+贪心】codeforces Game of the Rows

    http://codeforces.com/contest/839/problem/B [题意] 给定n组人,告诉每组人的人数,这些人要在飞机上坐座位 飞机上座位的分布看图可以知道,12  3456 ...

  6. bzoj5090组题 分数规划

    组题 Time Limit: 1 Sec  Memory Limit: 256 MBSubmit: 542  Solved: 114[Submit][Status][Discuss] Descript ...

  7. 关闭spring整合kafka时,消费者一直打印kafka日志

    在log4j.properties中添加如下代码 log4j.logger.org.apache.kafka.common.metrics.Metrics=OFF log4j.logger.org.a ...

  8. App竞品技术分析 (3)减小安装包的体积(转)

    http://blog.csdn.net/JspAndAsp/article/details/49339403 1 从几件小事说起 春节在家帮姐姐的iPhone手机安装市面上形形色色的App,忘记她是 ...

  9. ATcoder 1983 BBQ Hard

    E - BBQ Hard Time limit : 2sec / Memory limit : 256MB Score : 1400 points Problem Statement Snuke is ...

  10. babel 用法及其 .babelrc 的配置详解,想做前端架构,拒绝一知半解...

    Babel 官方介绍:将 ECMAScript 2015 及其版本以后的 javascript 代码转为旧版本浏览器或者是环境中向后兼容版本的  javascript 代码. 简而言之,就是把不兼容的 ...