Android开发技巧——设置系统状态栏颜色
开门见山,先来三张效果图:
然后我们再来讲如何实现以及如何快速地实现。
如何实现
实现设置系统状态栏颜色需要至少在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上还在用着半透明状态栏会带阴影来实现的设置状态栏颜色的效果好丑?
后记
- 上述项目见:https://github.com/msdx/status-bar-compat
- 有问题请在这里提:https://github.com/msdx/status-bar-compat/issues
- 我在5.0.1设置状态栏颜色遇到的失败问题,如果你能成功解决,欢迎到Github上提Pull Request。
- 这个项目中的代码几乎都不是我原创,我是代码片段的搬运工,并以我觉得的更好的方式将它们组织在一起,以及作了一些优化。
参考资料
- SystemBarTint: https://github.com/jgilfelt/SystemBarTint
- Android Lollipop Set Status Bar Text Color :http://stackoverflow.com/questions/30464234/android-lollipop-set-status-bar-text-color
- 《由沉浸式状态栏引发的血案》: http://www.jianshu.com/p/140be70b84cd?utm_source=tuicool&utm_medium=referral
- 《android状态栏一体化(改变状态栏的背景颜色) 》:http://blog.csdn.net/jdsjlzx/article/details/41643587
Android开发技巧——设置系统状态栏颜色的更多相关文章
- iOS平台设置系统状态栏(通知栏、顶部状态栏)样式背景颜色或透明
5+App开发 状态栏 配置系统状态栏样式 iOS平台可支持对系统状态栏样式的配置,在应用manifest.json文件的plus->distribute->apple下添加UIStatu ...
- Android开发技巧——高亮的用户操作指南
Android开发技巧--高亮的用户操作指南 2015-12-15补记: 发现使用PopupWindow进行遮罩层的显示,在华为P7上会有问题.具体表现为:画出来的高亮部分会偏下.原因为:通过view ...
- Android开发技巧——大图裁剪
本篇内容是接上篇<Android开发技巧--定制仿微信图片裁剪控件> 的,先简单介绍对上篇所封装的裁剪控件的使用,再详细说明如何使用它进行大图裁剪,包括对旋转图片的裁剪. 裁剪控件的简单使 ...
- Android开发技巧——自定义控件之使用style
Android开发技巧--自定义控件之使用style 回顾 在上一篇<Android开发技巧--自定义控件之自定义属性>中,我讲到了如何定义属性以及在自定义控件中获取这些属性的值,也提到了 ...
- Android开发技巧——写一个StepView
在我们的应用开发中,有些业务流程会涉及到多个步骤,或者是多个状态的转化,因此,会需要有相关的设计来展示该业务流程.比如<停车王>应用里的添加车牌的步骤. 通常,我们会把这类控件称为&quo ...
- Android开发技巧——使用PopupWindow实现弹出菜单
在本文当中,我将会与大家分享一个封装了PopupWindow实现弹出菜单的类,并说明它的实现与使用. 因对界面的需求,android原生的弹出菜单已不能满足我们的需求,自定义菜单成了我们的唯一选择,在 ...
- Android开发技巧——实现可复用的ActionSheet菜单
在上一篇<Android开发技巧--使用Dialog实现仿QQ的ActionSheet菜单>中,讲了这种菜单的实现过程,接下来将把它改成一个可复用的控件库. 本文原创,转载请注明出处: h ...
- Android开发技巧——自定义控件之增加状态
Android开发技巧--自定义控件之增加状态 题外话 这篇本该是上周四或上周五写的,无奈太久没写博客,前几段把我的兴头都用完了,就一拖再拖,直到今天.不想把这篇拖到下个月,所以还是先硬着头皮写了. ...
- Android开发技巧——自定义控件之自定义属性
Android开发技巧--自定义控件之自定义属性 掌握自定义控件是很重要的,因为通过自定义控件,能够:解决UI问题,优化布局性能,简化布局代码. 上一篇讲了如何通过xml把几个控件组织起来,并继承某个 ...
随机推荐
- 处理异常、常用类、反射、类加载与垃圾回收、java集合框架
异常处理概述 检查异常:检查异常通常是用户错误或者不能被程序员所预见的问题.(cheched) 运行时异常:运行时异常是一个程序在运行过程中可能发生的.可以被程序员避免的异常类型.(Unchecked ...
- [LeetCode] Diameter of Binary Tree 二叉树的直径
Given a binary tree, you need to compute the length of the diameter of the tree. The diameter of a b ...
- 使用Nwjs开发桌面应用体验
之前一直用.net开发桌面应用,最近由于公司需要转为nodejs,但也是一直用nodejs开发后台应用,网站,接口等.近期,需要开发一个客户端,想着既然nodejs号称全栈,就试一下开发桌面应用到底行 ...
- 计蒜客NOIP模拟赛(2) D1T2 表演艺术
凡和邻家男孩玩完了纸牌,兴致很高,于是准备了一场表演艺术对抗赛. 他特意请来了很多表演艺术家,分成绿黑两队,进行名为 PK,实则捞金的表演. 凡为了捞金,开设了一个赌局,在比赛开始之前招揽人们来押注谁 ...
- bzoj 3214: [Zjoi2013]丽洁体
Description 平时的练习和考试中,我们经常会碰上这样的题:命题人给出一个例句,要我们类比着写句子.这种往往被称为仿 写的题,不单单出现在小学生的考试中,也有时会出现在中考中.许多同学都喜欢做 ...
- 【SYZOI Round1】滑稽的树
Description zzsyz实验楼里面种了一棵滑稽树,只有滑稽之力达到大乘期的oier才能看到.虽然我们看不到,但是还是知道一些信息: 这真的是一棵树,由n个节点,n-1条边联通.一号滑稽果同时 ...
- [BZOJ]1042 硬币购物(HAOI2008)
失踪OJ回归. 小C通过这道题mark一下容斥一类的问题. Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买s ...
- bzoj1010[HNOI2008]玩具装箱toy 斜率优化dp
1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 11893 Solved: 5061[Submit][S ...
- TDMA over WiFi
0 引言 TDMA可以修正WiFi中DCF机制中连接速率不同终端间信道占用时间片公平性缺陷,从而提升整体WiFi网络的性能.著名的UBNT的网桥就用其独创的TDMA技术为其赢得了市场.以前是不同的公司 ...
- Thinkphp中的A 函数(Thinkphp3.2.3版本)
A函数是TP中实例化控制器的一个快捷函数,它的语法结构如下: A('模块/控制器') //当控制器层名称不是 Controller 时须这样写 A('模块/控制器','控制器层名称') 如果要调用的控 ...