开门见山,先来三张效果图:





然后我们再来讲如何实现以及如何快速地实现

如何实现

实现设置系统状态栏颜色需要至少在Android 4.4.2(API 19)以上。这是因为,在这个版本以下,没有任何的API可以帮助我们来实现。那么具体如何设置呢?

Android 4.4.2

实现

Android 4.4.2新增了一个特性,即可以设置系统状态栏为半透明。设置方法有两种,一是通过在主题style中添加以下属性:

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

二是通过在JAVA代码中设置,即以下代码:

Window window = activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

设置系统状态栏为半透明之后,我们就可以通过往Window窗口的decorView添加一个View,让它大小与系统状态栏一样,然后设置这个view的背景,就可以实现修改状态栏颜色的效果了。代码如下:

        ViewGroup decorViewGroup = (ViewGroup) window.getDecorView();
View statusBarView = new View(window.getContext());
int statusBarHeight = getStatusBarHeight(window.getContext());
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, statusBarHeight);
params.gravity = Gravity.TOP;
statusBarView.setLayoutParams(params);
statusBarView.setBackgroundColor(color);
decorViewGroup.addView(statusBarView);

其中获取状态栏高度的方法代码如下:

    private static int getStatusBarHeight(Context context) {
int statusBarHeight = 0;
Resources res = context.getResources();
int resourceId = res.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight = res.getDimensionPixelSize(resourceId);
}
return statusBarHeight;
}

然后在我们的Activity的onCreate方法中使用以上代码就可以了。

问题及解决方法

但是在使用之后,我们会发现,我们Activity的布局内容顶到了状态栏上去了,被状态栏及ActionBar所覆盖。解决方法很简单,只需要在我们的布局文件的根元素中设置以下属性:

android:fitsSystemWindows="true"

它的意思是使这个layout内嵌,也就是会为状态栏等留出空间,于是我们的布局就恢复正常了。

但是问题来了,假如你有几十个Activity,每一个都要修改它的布局文件,是一件让人沮丧的事情。于是,一番查找之后,我们似乎找到了答案。即通过在Application主题中配置这个属性。遗憾的是我们发现这样做之后,我们的Toast显示就不正常了,它的文字会超出黑色背景之外。

不过没关系,我们还有解决方法。那就是在setContentView()之后,加入以下代码:

    ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
View mChildView = mContentView.getChildAt(0);
if (mChildView != null) {
//注意不是设置 ContentView 的 FitsSystemWindows, 而是设置 ContentView 的第一个子 View . 预留出系统 View 的空间.
mChildView.setFitsSystemWindows(fitSystemWindows);
}

也就是在JAVA代码中找到我们Activity的内容的View,并给它设置这个属性。

Android 5.0.1

在Android 5.0.1(API 21)起,官方又为我们引入了一些特性,包括一个重要的方法:

window.setStatusBarColor(color);

看起来似乎很激动人心。要使它生效,必须设置一个FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS属性,并且确保FLAG_TRANSLUCENT_STATUS不被设置。

那好,我们来实现:

    Window window = activity.getWindow();
//取消设置透明状态栏,使 ContentView 内容不再覆盖状态栏
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//需要设置这个 flag 才能调用 setStatusBarColor 来设置状态栏颜色
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
//设置状态栏颜色
window.setStatusBarColor(color);

遗憾的是,在我手上的P7上并没有任何效果。据说要在主题当中设置colorPrimaryDark属性,但是我试过之后发现状态栏还是没有被设成我想要的颜色,并且可能显示成其他颜色。所以这种方法我最终没有采用。

Android 6.0

Android 6.0设置状态栏的颜色的方法与上面的一致,庆幸的是,它的设置有效,代码同上:

        //取消设置透明状态栏,使 ContentView 内容不再覆盖状态栏
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//需要设置这个 flag 才能调用 setStatusBarColor 来设置状态栏颜色
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
//设置状态栏颜色
window.setStatusBarColor(color);

由于与API 19设置状态栏半透明并添加一个View的实现方式不同,这里是直接设置状态栏的颜色的,所以如果我们的状态栏被设为白色的话,上面同样白色的系统状态就看不到了。不过,6.0的API新增了一个属性来解决这一问题。即,如果我们设置的状态栏颜色是接近于白色的话,可以在主题中添加以下属性:

<item name="android:windowLightStatusBar">true</item>

这样,系统状态的那些文字图标就会变成黑色了,如一开始我们所看到的第三张图。

通过JAVA代码来设置的话如下:

    View decor = window.getDecorView();
int ui = decor.getSystemUiVisibility();
if (lightStatusBar) {
ui |=View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
} else {
ui &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
}
decor.setSystemUiVisibility(ui);

如何快速的实现

那么,你真的要在项目中根据不同系统版本来写这么多代码吗?还要改style文件?为不同的系统版本创建不同的style文件来实现这个功能?

完全可以不用,因为我已经对它做了封装。你只需要两步,就可以完成。

在项目的build.gradle中声明以下依赖:

    compile 'com.githang:status-bar-compat:0.3'

在你的Activity中(最好是setContentView()被调用之后)添加以下代码:

    StatusBarCompat.setStatusBarColor(this, color, lightStatusBar);

不用考虑版本,不用考虑fitsSystemWindows问题,不用考虑状态栏被设置成白色后看不到系统状态的问题,并且兼容MIUI及Flyme。那么,当你在6.0的手机上看习惯这种纯色的状态栏之后,是不是觉得手机QQ在6.0上还在用着半透明状态栏会带阴影来实现的设置状态栏颜色的效果好丑?

后记

参考资料

Android开发技巧——设置系统状态栏颜色的更多相关文章

  1. iOS平台设置系统状态栏(通知栏、顶部状态栏)样式背景颜色或透明

    5+App开发 状态栏 配置系统状态栏样式 iOS平台可支持对系统状态栏样式的配置,在应用manifest.json文件的plus->distribute->apple下添加UIStatu ...

  2. Android开发技巧——高亮的用户操作指南

    Android开发技巧--高亮的用户操作指南 2015-12-15补记: 发现使用PopupWindow进行遮罩层的显示,在华为P7上会有问题.具体表现为:画出来的高亮部分会偏下.原因为:通过view ...

  3. Android开发技巧——大图裁剪

    本篇内容是接上篇<Android开发技巧--定制仿微信图片裁剪控件> 的,先简单介绍对上篇所封装的裁剪控件的使用,再详细说明如何使用它进行大图裁剪,包括对旋转图片的裁剪. 裁剪控件的简单使 ...

  4. Android开发技巧——自定义控件之使用style

    Android开发技巧--自定义控件之使用style 回顾 在上一篇<Android开发技巧--自定义控件之自定义属性>中,我讲到了如何定义属性以及在自定义控件中获取这些属性的值,也提到了 ...

  5. Android开发技巧——写一个StepView

    在我们的应用开发中,有些业务流程会涉及到多个步骤,或者是多个状态的转化,因此,会需要有相关的设计来展示该业务流程.比如<停车王>应用里的添加车牌的步骤. 通常,我们会把这类控件称为&quo ...

  6. Android开发技巧——使用PopupWindow实现弹出菜单

    在本文当中,我将会与大家分享一个封装了PopupWindow实现弹出菜单的类,并说明它的实现与使用. 因对界面的需求,android原生的弹出菜单已不能满足我们的需求,自定义菜单成了我们的唯一选择,在 ...

  7. Android开发技巧——实现可复用的ActionSheet菜单

    在上一篇<Android开发技巧--使用Dialog实现仿QQ的ActionSheet菜单>中,讲了这种菜单的实现过程,接下来将把它改成一个可复用的控件库. 本文原创,转载请注明出处: h ...

  8. Android开发技巧——自定义控件之增加状态

    Android开发技巧--自定义控件之增加状态 题外话 这篇本该是上周四或上周五写的,无奈太久没写博客,前几段把我的兴头都用完了,就一拖再拖,直到今天.不想把这篇拖到下个月,所以还是先硬着头皮写了. ...

  9. Android开发技巧——自定义控件之自定义属性

    Android开发技巧--自定义控件之自定义属性 掌握自定义控件是很重要的,因为通过自定义控件,能够:解决UI问题,优化布局性能,简化布局代码. 上一篇讲了如何通过xml把几个控件组织起来,并继承某个 ...

随机推荐

  1. scrapy.Spider的属性和方法

    scrapy.Spider的属性和方法 属性: name:spider的名称,要求唯一 allowed_domains:允许的域名,限制爬虫的范围 start_urls:初始urls custom_s ...

  2. for/range/break/continue

    #for智能循环 members=['武林至尊','宝刀屠龙','号令天下','莫敢不从'] for every in members:     print(every,len(every)) 武林至 ...

  3. SQL基础-----DDL

    1 (My)SQL入门 这里用了(My)SQL这样的标题,目的是介绍标准SQL的同时,也将MySQL在标准SQL上的扩展一同介绍给读者. 2:SQL分类 SQL语句主要可以划分为以下3个类别 .DDL ...

  4. TensorFlow学习笔记(MNIST报错修正 适用Tensorflow1.3)

    在Tensorflow实战Google框架下的深度学习这本书的MNIST的图像识别例子中,每次都要报错   错误如下: Only call `sparse_softmax_cross_entropy_ ...

  5. [Luogu 3768]简单的数学题

    Description 输入一个整数n和一个整数p,你需要求出$(\sum_{i=1}^n\sum_{j=1}^n ijgcd(i,j))~mod~p$,其中gcd(a,b)表示a与b的最大公约数. ...

  6. [ZJOI2008]瞭望塔

    题目描述 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安. 我们将H村抽象为一维的轮廓.如下图所示 我们可以用一条山的上方轮廓折线(x1, y1), ...

  7. [HAOI2009]逆序对数列

    题目描述 对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数.若对于任意一个由1~n自然数组成的数列,可以很容易求出有多少个逆序对数.那么逆序对数为k的这样 ...

  8. 【BZOJ2186】【SDOI2008】沙拉公主的困惑

    Description ​ 大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞票.房地产第一大户沙拉公主决定预测一下大富翁 ...

  9. Codeforces Round #438 B. Race Against Time

    Description Have you ever tried to explain to the coordinator, why it is eight hours to the contest ...

  10. bzoj4767两双手 容斥+组合

    4767: 两双手 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 684  Solved: 208[Submit][Status][Discuss] ...