Android 系统状态栏沉浸式/透明化完整解决方案

前言

网上已经有很多有关于系统状态栏的解决方案,这篇文章也不会有什么新奇的解决方案,都是本人经过自己试验,统计提炼出来的相对靠谱的一套解决方案.
如果是android大牛可以忽略本文,怕让您贱笑.只面向小白,帮助小白减少摸索的时间.

关于术语

网上有很多争论:

你这状态栏是变色龙状态栏,不是沉浸式的
这应该是沉浸式的状态栏吧,系统栏与actionbar颜色设为一致

我只想说去你妹的,老子只要自己的app的状态栏能和主题颜色一致就行了,定义那么多术语,让我等小白情以何堪?
吐槽归吐槽,但还是不得不去试着理解下这些术语怎么来的,引用这里的一段话:

  1. 沉浸式全屏模式
    隐藏status bar(状态栏)使屏幕全屏,让Activity接收所有的(整个屏幕的)触摸事件。
  2. 透明化系统状态栏
    透明化系统状态栏,使得布局侵入系统栏的后面,必须启用fitsSystemWindows属性来调整布局才不至于被系统栏覆盖。

因此,我就这样理解了:

沉浸式不就是隐藏状态栏嘛,状态栏不见了?这不就是app全屏模式嘛?wtf?

而透明式式状态栏就是让app的内容布局可以扩展到系统状态栏?这里有个问题就是为什么能在系统状态栏还显示的情况下,将内容布局扩展到系统状态栏?恩,这应该很好理解,就是Z坐标系的作用了,系统状态栏是覆盖在内容布局上面的,并且是透明的。

貌似这里所谓透明化系统状态栏才是本菜想要的,不管了,现在开始一一试验,至于这概念理解的对不对,管他呢?那到底应该叫什么,那我就叫自适应状态栏,行不行?

前提条件

让系统状态栏颜色随app主题颜色变化而变化这一设计,毫无疑问,也是向ios学习的:从android4.4开始引进的,并且在5.0进行了改进。因此,也只能将这一特性应用在android4.4以上的手机,无法做到全部适配。记得stormzhang(貌似是)曾说过:

作为一个android程序员,还能有什么比做出ios风格的app更感到悲哀的呢?哎...

两种情况下的解决方案:

  1. 使用toolbar
    这种方案相对简单,个人喜欢这种方案,本菜虽菜,但喜欢紧跟潮流。toolbar太好用了,
  2. 不使用toolbar

1. 使用toolbar的解决方案

这个方法参照了这里,薄荷app的toolbar适配方案

其基本原理就是:
theme里添加style: <item name="android:windowTranslucentStatus"> true </item>后,包含toolbar的内容布局就可以扩展至系统状态栏,状态栏会覆盖在toolbar上,如果此时使用android:fitsSystemWindows="true",就可以调整内容布局(估计也是在根布局上加padding)恢复到原来位置.但是,上面的解决方案确是给toolbar加上一个padding-top="25dp",这样就可以做到系统状态栏的颜色和toolbar的颜色保持一致.具体方案可以参照上面的薄荷app的方案链接.


简述下步骤(只是简述,有疑问请参照上面薄荷app的链接即可):

  1. 引入v7包,并在布局里添加toolbar
compile ‘com.android.support:appcompat-v7:22.2.1’
  1. 在代码中设置透明化:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
    local LayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
}

当然也可以在theme的样式文件里添加style:<item name="android:windowTranslucentStatus">true</item>,效果相同,但是大神们都说样式文件里设置在某些型号里不生效.ok,大家都在代码里设置就好了

  1. 给toolbar加上padding-top,toolbar代码如下
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" 
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="@dimen/toolbar_padding_top"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    android:background="#30469b">
        <TextView android:layout_gravity="center" 
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:textSize="20sp"
          android:text="@string/app_name"/>
</android.support.v7.widget.Toolbar>

4.其中android:paddingTop="@dimen/toolbar_padding_top"要在values中的styles文件里设为0dp,在values-v19的styles里设为25dp,原因不多说了

这样就可以达成了我们的目标,如果只是这样也就罢了,按照上面做就可以了,关键是本菜是喜欢紧跟潮流的,使用MD风格的DrawerLayout+NavigationView时,在android4.4的手机下,就会变这样了:


android4.4上的效果

很明显,drawerlayout并没用被扩展至系统状态栏,但在android5.0以上效果还是可以的,这让我很奇怪,只能归咎于5.0的优化了


android5.0上的效果

经过各种折腾终于想起来,可以把fitsSystemWindows的特性用在drawerlayout上试试,最后发现居然可以,最终将设置windowTranslucentStatus的代码调整如下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();    
    local LayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
    if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){
        //将侧边栏顶部延伸至status bar
        mDrawerLayout.setFitsSystemWindows(true);        
        //将主页面顶部延伸至status bar;虽默认为false,但经测试,DrawerLayout需显示设置
        mDrawerLayout.setClipToPadding(false);
    }
}

最终android4.4上也可以显示正常:


android4.4上修正后的效果

2. 不使用toolbar的解决方案

不使用toolbar时,而是actionbar时,因为actionbar不好定制,所以无法采用上面那个方法,只能采用其它方法,这里的方案主要参考这里:Translucent System Bar 的最佳实践
这篇简书看的本菜晕乎乎的,仔细看下来,其实都是基于一个原理:
不管有没有actionbar,内容布局的背景颜色一律设为主题颜色,然后有actionbar的话,就将actionbar与内容布局的背景颜色同时设为主题颜色,然后,每个内容布局的根布局都要设上fitsSystemWindows="true"进行调整,感觉超麻烦有没有?


不说多少,简述步骤:

  1. 在代码中设置透明化,步骤同上
  2. 设置内容布局的根布局的背景颜色为主题颜色,同时设置fitsSystemWindows="true"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorPrimary"
    android:fitsSystemWindows="true" 
    android:orientation="vertical">
  1. 在内容布局的下面再设置一层内容布局,设背景颜色为白色(或其它颜色):
<LinearLayout    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/c_light_white"
    android:gravity="center"
    android:orientation="vertical">

至此,这种方案也完成了,看下效果:


android4.4上的效果

可以看出,这种方案一般情况下,还是可行的,但是有三个问题:

  1. 如果用上drawerlayout+navigationview,actionbar就会覆盖在侧边栏上(如上图),暂时未找到解决方案,但是我想说你都用drawerlayout+navigationview了,为何不用toolbar,因此这个问题应该不是问题,况且还可以使用其它的侧边栏实现方式,各位道友可以试试
  2. 这种方案在每个根布局上都要设fitsSystemWindows="true"进行调整,当然上面也有优化方案,可仍然觉得很麻烦,
  3. 每个根布局里都要多加的一层布局来覆盖根布局的背景主题颜色

因此,这种方案的确不是上上之选.

总结

本文主要在考虑使用标题栏(actionbar/toolbar)的情况下,做出的方案,当然你也可以自定义标题栏,或者不使用标题栏;其实都可以基于上面一样的道理:

在状态栏透明化的前提下,调整顶部view的padding-top,来达到状态栏自适应一体化的目的

网上还有其它蛮多的解决方案,如:

  1. 使用开源库SystemBarTint,这个库也挺不错的,可以动态改变系统状态栏颜色,但是作者已经2年没有维护了,现在技术更新迭代这么快,鬼知道这个库会不会出现什么问题,因此可以放弃使用了
  2. 如果不怕麻烦,还可以new一个高度和状态栏一样高的view,插入到内容布局的上面,但是,想想都觉得麻烦,我也懒得试了

关于本文中的样例代码已上传至github,欢迎star,有问题也欢迎各位撸友,道友们来指正.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容