[Android必备基础]之状态栏处理

前言

NavigationBar就是手机底部的虚拟导航按键,在华为和小米手机上很常见;

Android状态栏的处理跟导航栏的处理极其相似,所以文章主要介绍状态栏的处理,需要了解导航栏方面的可以对照状态栏处理看代码进行了解即可,代码在Andme库中已提供;

Android状态栏对整个App而言是非常重要的,直接影响App的展示效果,市面上相关文章和第三方库也非常之多,但质量参差不齐,代码差异化也严重,容易搞得大家云里雾里,甚至一些star比较高的库,其可读性和质量似乎也有待提高;

加之之前曾对这一块的内容做过了解,此次重构Andme时也需要支持状态栏和导航栏的处理,但是却发现自己曾经所做的了解,早已烟消云散,好像自己对此一无所知;俗话说好记性不如烂笔头,特写此文以便未来再次需要了解相关模块时可以作为参考;

状态栏的发展经历过几大阶段,在4.4之前是无法操作状态栏的,可能国内部分厂商有提供相关功能支持。4.4开始官方提供栏状态栏的相关操作,之后5.0进行了完善,6.0做了补充,所以我们主要讲讲4.4、5.0、6.0这三个阶段。

4.4

4.4版本提供的状态栏功能不是很完善,加上目前4.4版本的手机市场占有率不高,基于这两点个人建议可以放弃4.4版本的状态栏支持。

4.4开始,官方提供了透明系统状态栏和沉浸式全屏模式两个概念,官方资料链接[1],本文只讲状态栏相关的内容(其实状态栏跟沉浸式息息相关);

简单来说,这个版本提供的功能,就是可以将布局内容延伸到状态栏的下面(即状态栏覆盖布局内容),除此之外别无其他,现在市面上的七七八八的各种花里胡哨的功能支持,其实都是经过了二次处理实现的,也正是如此,弄的五花八门,质量参差不齐。

将布局内容填充在状态栏之下有3种方式,其中第一种和第二种方式算是同一种原理的不同形式而已;

1、使用官方提供的新的主题(Deprecated)

使用新的主题Theme.Holo.NoActionBar.TranslucentDecorTheme.Holo.Light.NoActionBar.TranslucentDecor将系统状态栏设置为部分透明;

<style name="AppStyle" parent="@android:style/Theme.Holo.NoActionBar.TranslucentDecor">

此方式已不建议使用,在5.0以后,建议使用Material主题或者使用AppCompat相关的api; 原文:@deprecated Use Material themes on API 21+ or AppCompat on supported APIs

2、使用主题属性

在主题样式中添加windowTranslucentNavigationwindowTranslucentStatus样式属性

<style name="{Your Theme Name}">

其本质与第一种类似,第一种也不过就是在提供主题的时候设置了以上属性;

3、代码方式(推荐方式)

使用以下代码即可实现透明状态栏 activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

关于WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS的说明:

      /**

注释上已经对4.4透明状态栏的方方面面进行了说明;

上图

俗话说无图无真相,说个JB。

由于电脑存储空间有限,连个4.4的模拟器都运行不了,所以引用了其他博客的图片,如有侵权,请联系删除。

图片来源于:https://blog.csdn.net/shanshui911587154/article/details/86623646

图片来源https://blog.csdn.net/shanshui911587154/article/details/86623646

<figcaption style="box-sizing: border-box; margin: 0px; padding: 0px; text-align: center; color: rgb(136, 136, 136); line-height: 1.75; font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif; font-size: 0.8em;">图片来源https://blog.csdn.net/shanshui911587154/article/details/86623646</figcaption>

可以看到效果就是状态栏覆盖了布局;

小结

也就是说,4.4的状态栏,仅仅只是可以设置将布局内容显示在状态栏之下而已,别无其他,仅此而已,连修改状态栏颜色的功能都没有提供,至此4.4的状态栏功能到此结束,就这么简单,就是这个味儿

什么?怎么就结束了?隔壁王五家提供的库那可是可以设置不同颜色的状态栏哦,对面张三家提供的库更不得了,还可以跟状态栏设置渐变色背景,甚至显示朵花在上面都可以,为什么到你这就啥都没有了;

耶,小老弟别慌别慌,只要你喜欢,把状态栏的背景改成动画都可以,到时装逼绝对酷炫;这到底是怎么回事,听老哥我慢慢道来;

功能扩展

上面的效果图可以明显的看到,状态栏覆盖了布局,但是很多时候需求仅仅只是需要修改状态栏的背景色,其他的照旧。那怎么实现这个功能呢?

其实简单,既然布局可以延伸到状态栏之下,那么我们在布局的顶部放一个跟状态栏一样高度的View不就可以了,既然是我们放置的View,那么想设置什么颜色的背景岂不简单?至于渐变色背景那也不过是小菜一碟,甚至你想弄一个什么玛莎拉蒂奥克斯飞机xxx效果啥的,只要View支持,就都不成问题。

只不过由于大多数界面的需求都是如此,如果每个界面需要设置状态栏颜色我们都在布局中放置一个与状态栏同等高度的View,这不累死人啊,还能愉快的农药么?还能高兴的撸啊撸么?

所以封装,将这一层操作封装起来,这也是大多数第三方库采用的策略。在4.4-5.0之间的版本(其实也就主要是4.4的版本),在DecorView中添加了一个与状态栏等高的View用来控制状态栏的背景色

//以下代码来源于Andme库,其中FakeStatusBar是自定义View,其作用就是将自己的高度设置为状态栏的高度

万变不离其宗,要封装处理,可以有很多种不同的实现,我们只需要记住上面的小结,记住4.4到底提供了什么功能就好了。

为什么有些库提示要在setContentView之后设置状态栏颜色;这可能是因为DecorView是一个FrameLayout,如果先调用设置状态栏颜色的方法添加了等高的状态栏View,在调用setContentView添加View时,就会覆盖之前添加的等高的状态栏View吧(具体未测试)。

敲黑板

4.4版本只是提供了将布局内容延伸到状态栏之下显示的支持,具体使用方式前面已说明;所以如果要实现类似顶部图片显示在状态栏之下的需求,只需要设置启用这个功能即可实现;对于要控制状态栏背景色的,都是通过在状态栏下面放置一个与状态栏同样高度的View实现的。

5.0

状态栏的处理,不外乎就是想控制状态栏的背景色,或者把布局延伸到状态栏之下显示;在4.4版本提供的状态栏支持中,我们无法直接设置状态栏的背景色,而只能通过一些其他的方式实现,但是在5.0之后,官方提供了设置状态栏背景色的支持;

调用activity.window.statusBarColor = color方法即可设置状态栏的背景色,但是仅仅这样子还不行,我们看一下statusBarColor方法的说明:

    /**

注释上清楚的说明了,要让statsuBarColor生效,必须设置android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,并且不能设置android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS,所以完整代码如下

  val color = xxx

至此,5.0的状态栏的功能到此结束;5.0提供了设置状态栏背景色的支持,用于弥补4.4版本的不足。

诶诶诶,老哥,我这还是有很多疑惑啊,我这样设置之后,布局内容是会延伸到状态栏之下呢,还是不会呀,我这下子有点摸不着了,而且你这无图无真相啊。

我们认真看一下前面的代码,这段代码修改了状态栏的背景色,其清除了WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS标志,诶,这标志有点眼熟啊,好像在哪里见过;这标志是在4.4的时候增加的,其作用前面讲4.4版本时已说明,设置此标志之后,布局内容会延伸到状态栏之下,所以5.0设置状态栏颜色时清除了此标志才能使状态栏背景色生效,那么也就意味着上面的代码只会更改状态栏的背景色,而不会把布局内容延伸到状态栏之下,也就是说状态栏不会覆盖你的布局内容;我们运行一下上面代码看下效果:

image

那如果想要实现顶部图片显示在状态栏之下怎么处理呢?小老弟,我刚才讲了呀,那个啥啥啥标志,只要我们添加WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,就可实现此功能,跟4.4的方式一模一样。难道就这么简单?当然这么处理之后,由于我们没有设置状态栏颜色,此时的状态栏背景是一个半透明图层,效果如下:

image

那有没有办法更改这个状态栏背景呢,比如我看别人家的效果都是状态栏透明的;当然有办法,前面不是讲了怎么修改状态栏颜色么,我们将状态栏的背景色修改为透明的不就可以了么。

可是好像冲突了呢,设置状态栏颜色要移除WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS标志,设置状态栏能够覆盖布局要添加这个标志,一个功能实现要添加,一个功能实现不能添加,要同时拥有这两个功能,这不就冲突了么...,这可如何是好,自己也尝试了一下,设置颜色之后添加这个标志,发现状态栏的颜色没有变化,只是布局内容延伸到了状态栏之下(一切尽在意料之中);

我们再看一下WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS的注释说明(前面已提供,翻回去看看),其中有这一段注释:When this flag is enabled for a window, it automatically sets the system UI visibility flags {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} and {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}。 这个意思就是说,当跟window添加WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS标志之后,就会自动的跟system UI visiblity flags添加View#SYSTEM_UI_FLAG_LAYOUT_STABLEView#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN这两个标志,至于system UI visibility flags是什么,这里就先不多说(跟前面提到的沉浸式全屏模式息息相关,所以状态栏跟沉浸式全屏模式有着紧密联系),那么这就好办了,我们可以先设置状态栏颜色,然后手动添加这两个标志看行不行,代码如下:


实际运行效果如下:

image

至此5.0的状态栏到这里也就结束了。

6.0

4.4开始可以将布局内容延伸到状态栏之下,5.0开始可以设置状态栏背景色,也由此带来一个问题,状态栏的文字和图标是浅色(或白色)的,如果状态栏的背景色也是浅色(或白色),那将导致两者无法看得清楚,这肯定是一个糟糕的体验。要是我们能够设置状态栏文字和图标的颜色就好了。

6.0的出现也正式可以解决上述问题,6.0开始提供了View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR标志位,将状态栏设置为浅色模式;这里有一点比较难理解,添加这个标志位之后,状态栏的文字和图标(只是系统图标,第三方app的图标可能不支持变换)会显示成深色,以兼容状态栏背景色为浅色的模式。

    /**

从注释上可以看到,这个标志位要生效,也必须为window添加android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS标志,并且不能添加android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS ,所以要想使用浅色模式的状态栏,具体代码如下:

    //以下代码来源于Andme库

运行效果截图,状态栏文字和图标变成了深色:

image

另外补充一点:国内厂商中小米和魅族,在6.0之前的某些机型中就提供了此功能,但是在后来两个厂商也使用了官方的方式,所以对于这种第三方差异,对于当前的设备占有率考虑,我也认为可以忽略这方面的处理了。

至此状态栏到这里先告一段落,什么水滴屏,刘海屏什么的,就以后再说了,只能感叹一下,写文章不是一点点费时,真的是太费时间了。

Andme Github地址[2]

欢迎入群交流:QQ276097690

微信搜索“您的宇辰”了解更多内容。

如果您有更多的建议或者交流,欢迎入群讨论,添加公众号更能第一时间了解最新内容。

References

[1] 官方资料链接: https://developer.android.google.cn/about/versions/android-4.4
[2] Andme Github地址: https://github.com/SupLuo/andme

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

推荐阅读更多精彩内容

  • 关于Android沉浸式状态栏, 网上已经有很多开源库, 虽然开源库可以解决某些特定布局下的沉浸式状态栏问题, 但...
    水中沚_b078阅读 2,386评论 2 4
  • 去年曾对状态栏进行了一次总结,具体见安卓自定义StatusBar-布局内容延展及沉浸式状态栏实现。近期再一次做透明...
    zizi192阅读 4,328评论 1 55
  • 前言在使用App的过程中,如果细心观察,我们会发现,某些应用顶部菜单栏颜色会延伸到系统状态栏中,使得菜单栏和状态栏...
    heyzhuyue阅读 725评论 0 1
  • Android沉浸式状态栏 Android状态栏默认是固定的黑底白字,这肯定是不被伟大的设计师所喜爱的,更有甚者,...
    filimoo阅读 1,318评论 0 8
  • 1. 需求 平常项目中,对顶部状态栏Status Bar,以及底部导航栏Navigation Bar的操作一般可以...
    浪够_阅读 6,400评论 0 22