Android下多彩的StatusView的实现
概述
在上一个博文 Anroid沉浸式状态栏中提到了,画了一个图,这个图简单将我们的状态栏分为不同的2个维度来看状态栏。其中涉及的概念我不在赘诉,请返到Anroid沉浸式状态栏再去认识下这几个概念。本文中提到的[上节]就是Anroid沉浸式状态栏这篇文章。

实现
由于[上节]提到了基本的实现方法和一些基本概念,但是没有实际操作和演示,那我们现在就来一步步来去实现我们提到的三种状态栏的实现过程。
全屏模式下的透明状态栏
全屏模式下的透明状态栏,其他app实现这样方式我们肯定见过,如我们的启动页很多情况下就是全屏模式,但是这个还是和我们说的不太一样,不过今天我们介绍的这个是透明状态栏,但是仍然又有出入。
如下图是网易新闻的启动页:

但是不是我们需要的效果,这种是全屏模式时,当前页面获取焦点就显示一个有一定透明度的暗色状态栏。
网易新闻这种才是真正的浸入式状态栏,这个沉浸式让郭神讲的很透彻 --Android状态栏微技巧,带你真正理解沉浸式模式
我们希望的是小米天气的这种:

内容部分可以延伸到状态栏,且状态栏是透明的,无背景色,也就是我们的全屏模式。
按照我们上节拿来实践下。
public static void setFullSreen(Activity activity){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// 设置透明状态栏,这样才能让 ContentView 向上
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
我将一个图片铺满contentView。

这个截图是在4.4上完成的。
但是在6.0上的效果还差强人意:

这个是在我的N5手机上跑的,上面有灰色的阴影。不是完全透明,和我们的小气天气不太一样,好了还是用到上节的方法:
public static void setFullSreen(Activity activity){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
}else
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// 设置透明状态栏,这样才能让 ContentView 向上
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
这样就可以使得状态栏也透明了。

彩色状态栏
可能有些人会迷惑,为什么我们要设置彩色状态栏,在5.0可以直接设置主题来设置的,我要告诉你的是我们希望4.4上也有彩色的状态栏。上节我们提到了彩色状态栏的实现方法:就是先设置为屏幕模式下的透明状态栏,再在透明状态栏的垂直下方放置一个和状态栏同样高宽的view,我们操作他这个空白view的颜色,即可实现彩色状态栏。
好了我们贴出来我们的代码逻辑吧:
/**
*设置彩色的状态栏
*
* @param activity
* @param color 状态栏需要设置的背景颜色
* @param statusBarAlpha 状态栏需要设置的背景颜色的透明度
*/
public static void setColor(Activity activity, @ColorInt int color, int statusBarAlpha){
//先设置的全屏模式
setFullSreen(activity);
//在透明状态栏的垂直下方放置一个和状态栏同样高宽的view
addStatusBarBehind(activity,color,statusBarAlpha);
}
/**
* 添加了一个状态栏(实际上是个view),放在了状态栏的垂直下方
*/
public static void addStatusBarBehind(Activity activity, @ColorInt int color, int statusBarAlpha) {
//获取windowphone下的decorView
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
int count = decorView.getChildCount();
//判断是否已经添加了statusBarView
if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {
decorView.getChildAt(count - 1).setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
} else {
//新建一个和状态栏高宽的view
StatusBarView statusView = createStatusBarView(activity, color, statusBarAlpha);
decorView.addView(statusView);
}
setRootView(activity);
}
/**
* 设置根布局参数
*/
private static void setRootView(Activity activity) {
ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
//rootview不会为状态栏流出状态栏空间
ViewCompat.setFitsSystemWindows(rootView,false);
rootView.setClipToPadding(true);
}
private static StatusBarView createStatusBarView(Activity activity, int color, int alpha) {
// 绘制一个和状态栏一样高的矩形
StatusBarView statusBarView = new StatusBarView(activity);
LinearLayout.LayoutParams params =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
statusBarView.setLayoutParams(params);
statusBarView.setBackgroundColor(calculateStatusColor(color, alpha));
return statusBarView;
}
/**
* 获取状态栏高度
*
* @param context context
* @return 状态栏高度
*/
private static int getStatusBarHeight(Context context) {
// 获得状态栏高度
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
return context.getResources().getDimensionPixelSize(resourceId);
}
/**
* 计算状态栏颜色
*
* @param color color值
* @param alpha alpha值
* @return 最终的状态栏颜色
*/
private static int calculateStatusColor(int color, int alpha) {
float a = 1 - alpha / 255f;
int red = color >> 16 & 0xff;
int green = color >> 8 & 0xff;
int blue = color & 0xff;
red = (int) (red * a + 0.5);
green = (int) (green * a + 0.5);
blue = (int) (blue * a + 0.5);
return 0xff << 24 | red << 16 | green << 8 | blue;
}
其中状态栏的view就是一个简单的view,贴出来的这个类吧:
public class StatusBarView extends View {
public StatusBarView(Context context, AttributeSet attrs,int style) {
super(context, attrs,style);
}
public StatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public StatusBarView(Context context) {
super(context);
}
}
搞定,我们就可以来动态改变状态栏的颜色了。
calculateStatusColor 方法中的alpha是0-255的,0的时候其实是不透明的,当设置255相当于statusview背景透明,即为默认色黑色。
可用的函数是 public static void setColor(Activity activity, @ColorInt int color, int statusBarAlpha)和setFullSreen
小结
Now现在这个工具类就算是OK,对于代码的侵入基本上为零,直接拿来当工具类,不用改主题,简单易容用。也为大家提供一个思路,这个只是实现的基本功能,一些复杂的定制的情况,可以随机应变,自由组合使用。
实现状态栏,无非是将4.4-5.0 和5.0+的分别实现,当然配合decorview和 ViewCompat.setFitsSystemWindows(view,boolean)使用效果更佳。
拓展阅读
在改变状态栏颜色时,我们需要注意的是默认的状态栏字体颜色都是黑色的,但是若是背景为暗色,上面的时间、电量等还等看到很清晰,但是若是遇到了全屏模式下状态栏垂直下方的view是白色的或者接近白色,那岂不是看不见状态栏上的字么?
是的!
所以有人提出需要改状态栏的字体颜色了,这个在知乎上火了一阵,所以把这个拓展部分留一个知乎的链接 ----android开发,修改状态栏字体颜色?
Android下多彩的StatusView的实现的更多相关文章
- Android下/data/data/<package_name>/files读写权限
今天将更新模块拿到android上面测试的时候,发现在创建writablepath.."upd/"目录的时候出现Permission Denied提示BTW:我使用的是lfs来创建 ...
- Android下Cocos2d创建HelloWorld工程
最近在搭建Cocos2d的环境,结果各种问题,两人弄了一天才能搞好一个环境-! -_-!! 避免大家也可能会遇到我这种情况,所以写一个随笔,让大家也了解下如何搭建吧- 1.环境安装准备 下载 tadp ...
- Android下读取logcat的信息
有时我们需要在程序执行进程中遇到一些异常,需要收集一logcat的信息,android下就可以使用以下方法获取: private static String getLogcatInfo(){ Stri ...
- Android下OpenCV的环境搭建
目录(?)[-] 前言 系统环境 相关工具 Android ADT环境搭建 Android SDK环境变量的配置 Android NDK的安装与配置 OpenCV for Android 环境搭建 基 ...
- Android下添加新的自定义键值和按键处理流程
Android下添加新的自定义键值和按键处理流程 说出来不怕大家笑话,我写这篇博客的原因在于前几天去一个小公司面试Android系统工程师,然后在面试的时候对方的技术总监问了我 ...
- Android下的数据储存方式(三)
Android下最好的数据储存方式:关系型数据库sqlite. 数据库的创建:使用SqliteOpenHelper类 结合SqliteOpenHelper类和SQLiteDatabase类的帮 ...
- 无废话Android之android下junit测试框架配置、保存文件到手机内存、android下文件访问的权限、保存文件到SD卡、获取SD卡大小、使用SharedPreferences进行数据存储、使用Pull解析器操作XML文件、android下操作sqlite数据库和事务(2)
1.android下junit测试框架配置 单元测试需要在手机中进行安装测试 (1).在清单文件中manifest节点下配置如下节点 <instrumentation android:name= ...
- 转:RTC搭建android下三层应用程序访问服务器MsSql-客户端
原文:http://www.cnblogs.com/delphi007/p/3346084.html android下stringgrid已知问题: 通过点击时获取对应行的值有问题,在win下调试正常 ...
- 转:RTC搭建android下三层应用程序访问服务器MsSql-服务器端
原文:http://www.cnblogs.com/delphi007/p/3346061.html 前几天通过Ro搭建webservice,然后在android下调用,虽然已近成功,但是返回的数据库 ...
随机推荐
- 列表和元组的基本操作,for遍历,range
1,list(增删改查):列表可以装大量数据,不限制数据的类型(int,str,bool, list,tuple,dict,set),表示方法用[ ],list和sttr有区别,list可以直接在原 ...
- Hibernate 之 Persistence
分享自: http://blog.csdn.net/jnqqls/article/details/8276059 在我们之前的文章已经了解到,Hibernate的汉语解释叫做冬眠,而这个冬眠我个人理 ...
- YTU 2579: 填空题----删除指定字符
2579: 填空题----删除指定字符 时间限制: 1 Sec 内存限制: 128 MB 提交: 164 解决: 61 题目描述 小明想要做个小程序,能够删除字符串中特定的字符. 例如:想要在下面 ...
- ubuntu1.8安装lnmp失败
兴致冲冲的安装好ubuntu1.8. 想安装lnmp,结果失败,失败,失败. 一遍由一遍,很痛苦. 每一遍都要半个小时,甚至更久. 等来的就是失败. 看日志也看不出头绪来. ============= ...
- 一步一步学Silverlight 2系列(2):基本控件
述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, ...
- coderfoces446c (斐波那契数列)
题目描述: 区间增值,但是每一项增加的值为Fi - l + 1,F[i]为斐波那契数列,求区间和? 考虑线段树,刚开始想用斐波那契数列的前n项和,可是推不出来,考虑到每个区间的增值序列都是一段斐波那契 ...
- 从0开始学习Hadoop(1) 环境准备 Win7环境+VirtureBox+Ubuntu
虚拟机:VirtureBox 3.18 下载地址: https://www.virtualbox.org/ 操作系统:Ubuntu 版本:ubuntu-15.04-desktop-amd64.iso ...
- 《10 minutes to pandas》(转)
原文出处:http://pandas.pydata.org/pandas-docs/stable/10min.html 10 Minutes to pandas This is a short int ...
- STM32F4 LTDC学习
很久没有写东西了,也很久没看文档了吼吼,觉得有点无聊,找来F4看看,主要看F429.督促自己多看多记录. 首先配置同步时序先看参考手册 下面看一个实际例子,一块439的开发板 设置: LTDC_Ini ...
- ChartCtrl源码剖析之——CChartGrid类
CChartGrid类用来绘制波形区域中的表格,当绘制波形时波形就显示在这些表格上面.它处于该控件的区域,如下图所示: CChartGrid类的头文件. #if !defined(AFX_CHARTG ...