概述

在上一个博文 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的实现的更多相关文章

  1. Android下/data/data/<package_name>/files读写权限

    今天将更新模块拿到android上面测试的时候,发现在创建writablepath.."upd/"目录的时候出现Permission Denied提示BTW:我使用的是lfs来创建 ...

  2. Android下Cocos2d创建HelloWorld工程

    最近在搭建Cocos2d的环境,结果各种问题,两人弄了一天才能搞好一个环境-! -_-!! 避免大家也可能会遇到我这种情况,所以写一个随笔,让大家也了解下如何搭建吧- 1.环境安装准备 下载 tadp ...

  3. Android下读取logcat的信息

    有时我们需要在程序执行进程中遇到一些异常,需要收集一logcat的信息,android下就可以使用以下方法获取: private static String getLogcatInfo(){ Stri ...

  4. Android下OpenCV的环境搭建

    目录(?)[-] 前言 系统环境 相关工具 Android ADT环境搭建 Android SDK环境变量的配置 Android NDK的安装与配置 OpenCV for Android 环境搭建 基 ...

  5. Android下添加新的自定义键值和按键处理流程

            Android下添加新的自定义键值和按键处理流程     说出来不怕大家笑话,我写这篇博客的原因在于前几天去一个小公司面试Android系统工程师,然后在面试的时候对方的技术总监问了我 ...

  6. Android下的数据储存方式(三)

      Android下最好的数据储存方式:关系型数据库sqlite.   数据库的创建:使用SqliteOpenHelper类 结合SqliteOpenHelper类和SQLiteDatabase类的帮 ...

  7. 无废话Android之android下junit测试框架配置、保存文件到手机内存、android下文件访问的权限、保存文件到SD卡、获取SD卡大小、使用SharedPreferences进行数据存储、使用Pull解析器操作XML文件、android下操作sqlite数据库和事务(2)

    1.android下junit测试框架配置 单元测试需要在手机中进行安装测试 (1).在清单文件中manifest节点下配置如下节点 <instrumentation android:name= ...

  8. 转:RTC搭建android下三层应用程序访问服务器MsSql-客户端

    原文:http://www.cnblogs.com/delphi007/p/3346084.html android下stringgrid已知问题: 通过点击时获取对应行的值有问题,在win下调试正常 ...

  9. 转:RTC搭建android下三层应用程序访问服务器MsSql-服务器端

    原文:http://www.cnblogs.com/delphi007/p/3346061.html 前几天通过Ro搭建webservice,然后在android下调用,虽然已近成功,但是返回的数据库 ...

随机推荐

  1. Codeforces 757 D. Felicity's Big Secret Revealed 状压DP

    D. Felicity's Big Secret Revealed   The gym leaders were fascinated by the evolutions which took pla ...

  2. hdfs对namenode format 之后 应该首先检查内存消耗情况,以判断是否支持开启yarn

    http://hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-common/yarn-default.xml  3.0.0 yarn.sc ...

  3. rabbitmq kafka storm

    rabbitmq:实时消息传递 kafka:消息的持久化 storm:使用拓扑逻辑进行

  4. android NDK 使用(多个)静态库生成动态库

    android NDK 使用(多个)静态库生成动态库. 1.编写Android.mk文件:如下两种方式都可以,用于NDK编译工具生成的两个.a文件来生成最终的libtwolib-second.so动态 ...

  5. eclipse svn修改用户名密码

    1,svn客户端删除 2,eclipse 补充,上图为网友资料,但实际操作过程中,发现eclipse中svn为svnkit,但相应目录下无.keyring文件,最后按步骤2删除auth下所有文件,再次 ...

  6. I.MX6 dhcpcd 需要指定网卡

    /************************************************************************** * I.MX6 dhcpcd 需要指定网卡 * ...

  7. robotframework收藏

    收藏文章 http://www.360doc.com/userhome/38592059

  8. 杂项:Java un

    ylbtech-杂项:Java 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   作者:ylbtech出处:http://ylbtech. ...

  9. java.lang.NoSuchMethodError: org.springframework.web.context.ConfigurableWebApplicationContext.setId

    运行spring报了这个错误,网上说是spring版本冲突,检查maven依赖,发现我依赖的是spring-core.3.0.5,但是spring-orm和spring-tx依赖了spring-bea ...

  10. Python 元组、列表

    Python中,最常用的数据结构就是序列了.序列有以下几种:元组,列表,字符串等.注:代码都是在IDE中编辑的,没有用交互式环境. 一.元组(tuple) 元组其实有点类似C++中的数组,即一旦指定了 ...