Android沉浸式状态栏实现

应用市场上App越来越多的出现沉浸式状态栏的设计(如下图所示)状态栏和导航栏具有相同的颜色。Android在4.4开始对于该种效果的支持,而在4.4之下,状态栏只是黑框,无法控制。同时在4.4和5.0及其之上的版本对该种效果的支持又有所差异,因此要实现该种效果,可以将4.4归为一类,5.0及其之上归为一类。接下来,我们将一步步来在4.4和5.0及其之上来实现如下所示效果。

导航栏问题

在Android中,顶部导航栏目前常用的两种实现方式,一个是通过Toolbar,一个是通过自定义View的方式来实现。两种方式各有利弊。Toolbar为官方指定规范,开发者使用更方便,但可拓展性差,对于一些特殊的展示效果无法实现,而通过自定义方式的方式,可以支持更多展示效果,但却需要我们写更多的代码。两种方式在实现状态栏沉浸上也有所差别。

去掉Title

  • Toolbar默认主题会具有一个title,当我们使用Toolbar的时候,而没有去掉title,应用则会crash,报出如下所示错误。 

因此在使用Toolbar 的时候,我们需要style中添加如下属性配置


  1. <item name="windowNoTitle">true</item> 

当然我们也可以通过代码动态去掉title,但当我们的主题从Theme.AppCompat作为父类继承的时候,通过代码并不可以去掉title。

自定义导航栏

当我们未设置windowNoTitle属性的时候,在导航栏之上有title。显然和我们要实现导航栏的沉浸式有所违背,因此实现对于导航栏的沉浸,

<item name="windowNoTitle">true</item>该配置是必不可少的。

设置状态栏透明

去掉title之后,是否我们就可以实现上述的效果了呢?

这个时候,我们发现状态栏还是黑色,并没有沉浸,需要我们将状态栏设置为透明。


  1. <item name="android:windowTranslucentStatus">true</item> 

该属性只有在在4.4和高于4.4版本上可以进行该属性的配置,但是在更低版本上则无法使用。配置该属性之后,执行效果如下图所示。

解决导航栏上移问题

这个时候,Toolbar被整体上移了,导致其部分功能也进入了状态栏之下,包括导航栏的内容也到了状态栏位置之中,显然这是不符合我们最初的要求的。如何解决这个问题?我们在Toolbar中添加fitSystemWindows属性,即可使得toolbar的上部空出一个高度,使得Toolbar内容部分脱离状态栏。


  1. <android.support.v7.widget.Toolbar 
  2.        android:id="@+id/toolbar" 
  3.        android:fitsSystemWindows="true" 
  4.        android:layout_width="match_parent" 
  5.        android:layout_height="wrap_content"> 
  6.    </android.support.v7.widget.Toolbar>  

得到我们最终想要得到的效果

自定义导航栏与之实现类似。

fitsSystemWindows属性

前面对Toolbar的设置是在Toolbar中添加的fitSystemWindows属性,那么当我们将其属性添加到Toolbar所在的最外层的布局会怎么样呢?


  1. <RelativeLayout 
  2.     xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     xmlns:tools="http://schemas.android.com/tools" 
  4.     android:id="@+id/activity_toolbar" 
  5.     android:layout_width="match_parent" 
  6.     android:layout_height="match_parent" 
  7.     android:fitsSystemWindows="true" 
  8. tools:context="com.example.netease.toolbardemo.activity.ToolbarActivity"> 
  9.  
  10.     <android.support.v7.widget.Toolbar 
  11.         android:id="@+id/toolbar" 
  12.         android:layout_width="match_parent" 
  13.         android:layout_height="wrap_content"> 
  14.     </android.support.v7.widget.Toolbar> 
  15.  
  16. </RelativeLayout>  

执行之后,可以看到和之前未设置状态栏透明时的效果相同。

那么这个fitSystemWindows工作的原理是什么呢?通过上述实验,不难发现,对于沉浸状态栏的控制,该属性起到了一个很关键的作用。

接下来通过一个实验来验证下,该属性所起的作用,在Toolbar所在的布局中,在布局的底部添加一个Button.


  1. <android.support.v7.widget.Toolbar 
  2.         android:id="@+id/toolbar" 
  3.         android:fitsSystemWindows="true" 
  4.         android:layout_width="match_parent" 
  5.         android:layout_height="wrap_content"> 
  6.     </android.support.v7.widget.Toolbar> 
  7.  
  8.     <Button 
  9.         android:text="Test" 
  10.         android:layout_width="match_parent" 
  11.         android:layout_height="wrap_content" 
  12.         android:background="@color/colorAccent" 
  13.         android:layout_alignParentBottom="true"/>   

当我们将该属性设置到按钮上,又会发生什么呢?


  1. <Button 
  2.        android:text="Test" 
  3.        android:fitsSystemWindows="true" 
  4.        android:layout_width="match_parent" 
  5.        android:layout_height="wrap_content" 
  6.        android:background="@color/colorAccent" 
  7.        android:layout_alignParentBottom="true"/>  

通过比较可以很明显的看出,设置了fitsSystemWindows属性的View在其上部被设置了一个padding。根据之前做的实验,我们可以知道当我们设置了窗口状态栏透明之后,整个内容视图会向上移动了一个状态栏的高度,而当前为该View增加的padding的大小是不是和其高度相同呢?


  1. Button btn = (Button) findViewById(R.id.test_btn); 
  2.  Log.i("padding", btn.getPaddingTop()+""); 
  3.  Rect frame = new Rect(); 
  4.  getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); 
  5.  Log.i("height", frame.top+"");  

获取按钮的padding高度和状态栏的高度,我们可以得到如下日志。

通过实验我们可以得出结论,fitSystemWindows属性会对所设置的View增加一个top padding,因此当我们在实现让导航栏沉浸的时候,设置窗口状态栏的透明会使得视图整体上移,而借助fitSystemWindows属性的功能,为视图中最顶部的View设置一个和状态栏高度相同的padding,使得导航栏不会被顶到状态栏内。

当我们在一个视图中,多个View设置该属性时,发现只有第一个设置该属性的View会起作用,在视图布局上,自上而下的第一个View其作用。层级上则为最顶级的View上首先其作用。因此其功能归纳为:

  • 为设置该属性的View增加一个和状态栏高度相同的toppadding
  • 当视图中有多个View被设置了该属性,那么只布局上最顶部的View起作用

5.0及其以上

至此,我们可以完美的实现一个状态栏的沉浸,上述的实现是在Android 4.4版本上,在视图的最上部,会有一个黑色渐变的阴影,而在5.0设备上的展示效果如下所示,在状态栏上整个都会有一个阴影。当然不同厂家对此也有自己的一些优化,比如魅族在4.4上是不具有阴影的。

对于5.0及其之上,官方提供了对状态栏颜色控制的相应API,我们可以通过代码来控制状态栏的颜色,实现如下效果。

实现代码


  1. if(Build.VERSION.SDK_INT >= 21) { 
  2.             Window window = getWindow(); 
  3.             //取消设置透明状态栏,使 ContentView 内容不再沉浸到状态栏下 
  4.             window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 
  5.             //需要设置这个 flag 才能调用 setStatusBarColor 来设置状态栏颜色 
  6.             window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 
  7.             //设置状态栏颜色 
  8.             window.setStatusBarColor(getResources().getColor(R.color.yx_red)); 
  9.         }  

据此可以看出,当我们在5.0及其之上的实现中,可以不用进行状态栏透明的设置和fitSystemWindows属性的设置,直接通过代码来控制,但为了适应4.4版本,建议在代码中仍然按之前的方式实现,如果想在5.0及其高版本中实现去阴影,再手动在代码中控制。

作者:Jensen

来源:51CTO

时间: 2024-10-23 08:13:50

Android沉浸式状态栏实现的相关文章

关于Android沉浸式状态栏的问题

问题描述 关于Android沉浸式状态栏的问题 通过在每个activity中添加这样代码的方式实现的: 但是在有些手机上,下方的三个基础操作键时这样的: 这时候点击触发的是系统的三个键而不是想要点击的下方的几个按钮了. 为什么会这样,沉浸式除了状态栏之外也会影响这里吗?应该如何解决 解决方案 简要:android从4.4版本及以后加入了沉浸式状态栏的设置,但是也有一些问题,特别是自定义的最上面导航栏时,会出现一些问题,我想就我遇到的问题给大家一些讲解. 设置方法: 第一行代码:透明状态栏 第二行

Android沉浸式状态栏 如何改变状态图标和文字的颜色

问题描述 Android沉浸式状态栏 如何改变状态图标和文字的颜色 当我把状态栏设置成白色的时候文字和图标都看不到,而QQ却可以.求助~~~ 解决方案 改变状态栏文字的颜色android 沉浸式之改变小米状态栏颜色 解决方案二: 我是来领积分的啦啦啦啦啦啦啦啦啦 解决方案三: 没看懂什么鬼啊!一串英语搞什么

Android沉浸式状态栏与输入框上移的冲突问题

问题描述 Android沉浸式状态栏与输入框上移的冲突问题 在应用中设置了沉浸式状态栏但是输入框在输入法弹出后不自动上移了不做沉浸式就会上移怎么解决这个冲突做了沉浸式后android:windowSoftInputMode=""stateVisible|adjustResize""这个属性就没效果了 解决方案 http://blog.csdn.net/carlos1992/article/details/46773059 解决方案二: android:windowS

Android沉浸式状态栏微技巧(带你真正理解沉浸式模式)_Android

 其实说到沉浸式状态栏这个名字我也是感到很无奈,真不知道这种叫法是谁先发起的.因为Android官方从来没有给出过沉浸式状态栏这样的命名,只有沉浸式模式(Immersive Mode)这种说法.而有些人在没有完全了解清楚沉浸模式到底是什么东西的情况下,就张冠李戴地认为一些系统提供的状态栏操作就是沉浸式的,并且还起了一个沉浸式状态栏的名字. 比如之前就有一个QQ群友问过我,像饿了么这样的沉浸式状态栏效果该如何实现? 这个效果其实就是让背景图片可以利用系统状态栏的空间,从而能够让背景图和状态栏融为一

Android 沉浸式状态栏及悬浮效果_Android

一.概述 现在大多数的电商APP的详情页长得几乎都差不多,几乎都是上面一个商品的图片,当你滑动的时候,会有Tab悬浮在上面,这样做用户体验确实不错,如果Tab滑上去,用户可能还需要滑下来,在来点击Tab,这样确实很麻烦.沉浸式状态栏那,郭霖说过谷歌并没有给出沉浸式状态栏这个明白,谷歌只说了沉浸式模式(Immersive Mode).不过沉浸式状态栏这个名字其实听不粗,随大众吧,但是Android的环境并没有iOS环境一样特别统一,比如华为rom的跟小米rom的虚拟按键完全不一样,所有Androi

Android沉浸式状态栏设计的实例代码

本文介绍了android沉浸式状态栏,分享给大家,希望对大家有帮助 一.概述 现在主流的App设计风格很多都用到了Materail Design,今天我们就来简单的实现一下改变状态栏颜色.让状态栏透明这两种效果. 二.实现状态栏设置颜色 我们写一个工具类StatusBarUtils 代码如下: /** * 设置状态栏颜色 * * @param activity */ public static void setStatusColor(Activity activity, int color) {

解决Android 沉浸式状态栏和华为虚拟按键冲突问题

对于现在的 App 来说,布局页面基本都会用到沉浸式状态栏,单纯的沉浸式状态栏很容易解决,但是在华为手机上存在一个底部虚拟按键的问题,会导致页面底部和顶部出现很大的问题,比如页面底部导航栏被按键覆盖,导致底部无法操作,顶部状态栏布局被撑的很高,丑的不忍直视,这里就将两者的冲突问题一并解决!先看下实现的效果图: 这是我自己的手机,OnePlus 3T 7.1.1版本(免费广告,没给我钱的啊),不是华为的手机,但是有个虚拟按键可以设置,可以看到底部导航栏没有问题,顶部状态栏也成功实现,效果图看完,下

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

以前写过一个沉浸式状态栏 的实现方式  Android 沉浸式状态栏 实现方式一 现在有个更为简单的实现方式 . 相关链接 http://www.apkbus.com/forum.php?mod=viewthread&tid=255929&extra=page%3D3%26filter%3Dsortid%26orderby%3Ddateline%26sortid%3D12 1.效果图              demo 的 github 地址  https://github.com/zyj

Android 沉浸式状态栏及悬浮效果

一.概述 现在大多数的电商APP的详情页长得几乎都差不多,几乎都是上面一个商品的图片,当你滑动的时候,会有Tab悬浮在上面,这样做用户体验确实不错,如果Tab滑上去,用户可能还需要滑下来,在来点击Tab,这样确实很麻烦.沉浸式状态栏那,郭霖说过谷歌并没有给出沉浸式状态栏这个明白,谷歌只说了沉浸式模式(Immersive Mode).不过沉浸式状态栏这个名字其实听不粗,随大众吧,但是Android的环境并没有iOS环境一样特别统一,比如华为rom的跟小米rom的虚拟按键完全不一样,所有Androi

Android 沉浸式状态栏与隐藏导航栏实例详解

1 前言 一般我们在Android的APP开发中,APP的界面如下: 可以看到,有状态栏.ActionBar(ToolBar).导航栏等,一般来说,APP实现沉浸式有三种需求:沉浸式状态栏,隐藏导航栏,APP全屏 沉浸式状态栏是指状态栏与ActionBar颜色相匹配, 隐藏导航栏不用多说,就是将导航栏隐藏,去掉下面的黑条. APP全屏是指将状态栏与导航栏都隐藏,例如很多游戏界面,都是APP全屏. 所以,在做这一步时,关键要问清楚产品狗的需求,免得白费功夫. 下面,分别来介绍这三种方式的实现. 2