android状态栏总结
- 针对状态栏的操作,只针对4.4kitKat(含)以上的机型,部分国产rom会失效,目前发现的有华为的EMUI
- Activity必须是
noActionbar主题- 本文基于StatusBarUtils略作修改,感谢作者laobie
- 本文源码地址
相关属性重温
- FitsSystemWindows
在使用FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS、FLAG_TRANSLUCENT_STATUS挤占了状态栏的高度的时候,我们的布局文件也跟着顶到了状态栏上。通过FitsSystemWindows,系统会把app布局文件的paddingTop修改成状态栏的高度,达到适配的效果
false顶到状态栏
android.R.id.content
通过它我们可以在不需要知道ID的情况下,访问当前Activity根节点,一般是ContentFrameLayout类型,通过((ViewGroup)findViewById(R.id.content)).getChildAt(0);可以获取到我们布局xml的根节点getDecorView()
通过他,我们可以获取到整个Window界面的最顶层View。我们用的很多的findViewById(),就是基于这个DecorView查找里面的子节点的。比如Activity主题是Theme.AppCompat.Light.NoActionBar的组织层级如下,
为什么嵌套那么深,因为各个层次可能都会有几个ViewStub方便注入,只是我们现在的主题用不到就是空了。
下面开始实战了,一般我们用的比较多的是透明状态栏、设置状态栏颜色、
DrawerLayout盖在状态栏上三种。
1. 透明状态栏
这种情况一般用于把图片延伸到状态栏上,图片还分两种
- 作为
background的全屏大图 - 作为
ImageView控件存在,一般只占屏幕高度的一部分
这两种情况下的处理方式还不一样,具体看下文
/** * 使状态栏透明 */
private static void transparentStatusBar(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
}
else {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
}
上面的代码针对5.0以上或者4.4以上5.0以下的机型,让其状态栏透明、导航栏半透明,效果如下:
dump了下节点信息,我们发现布局的paddingTop从(50px状态栏高度)被修改成了0px。从而让图片延伸到了状态栏
这种情况下,对app布局文件通过设置FitsSystemWindows就可以完成适配了
/**
* 获取activity的根节点
*@param activity
*@return
*/
public static ViewGroup getAppRootView(Activity activity) {
return (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
}
/**
*将目标View的paddingTop从0设置为状态栏的高度
*/
private static void setRootViewFitSystemWindow(Activity activity) {
ViewGroup rootView = getAppRootView(activity);
rootView.setFitsSystemWindows(true);
rootView.setClipToPadding(true);
}
注意!!要延伸到状态栏的图片,如果不是根节点的背景图,而是一个ImageView控件,那么就不能设置setFitsSystemWindows了,原因参考上图红框。这种情况下,为了防止顶到状态栏,需要手动在xml里通过paddingTop、marginTop调整标题栏元素位置达到适配。类似下图
2. 状态栏颜色
设置状态栏颜色的步骤和透明类似,差别在于5.0以下机型无法直接设置状态栏颜色,我们可以模拟一个纯色的View放到状态栏下面间接达到着色效果。放置的父层级我们选择DecorView
如果发现状态栏颜色设置无效,有可能是布局文件的root节点加了
backgroundColor所致
/**
*
设置状态栏颜色
*
* @param activity 需要设置的activity
* @param color 状态栏颜色值
* @param statusBarAlpha 状态栏透明度
*/
public static void setColor(Activity activity, int color, int statusBarAlpha) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().setStatusBarColor(UIUtils.calcColorWithAlpha(color, statusBarAlpha));
} else {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
insertMockStatusBackgroundView(decorView, color, statusBarAlpha);
}
setRootViewFitSystemWindow(activity);
}
上面的代码判断DecorView下第0个View是不是我们自定义的StatusbarView类型,如果是则设置颜色,否则创建一个纯色控件插入到
DecorView内,同时布局内容上间距腾出给纯色控件。
3. DrawerLayout盖在状态栏上
DrawerLayout主要有两个子元素1:内容View 2:侧滑栏
侧滑栏必然要在内容View后面以覆盖前者
所以我们要做的有2步
- 插入纯色控件到内容View(如果不是LinarLayout需要考虑内容View元素重新排列)
- DrawerLayout设置
fitSystemWindow=false;以覆盖到状态栏上
代码如下:
/** * 为DrawerLayout 布局设置状态栏变色
*
* @param activity 需要设置的activity
* @param drawerLayout DrawerLayout
* @param color 状态栏颜色值
* @param statusBarAlpha 状态栏透明度
*/public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, int color, int statusBarAlpha) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return; }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
} else {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
//如果内容view不是LinearLayout,则需要重新排列内容view子元素的内容
insertMockStatusBackgroundView(contentLayout, color, statusBarAlpha);
drawerLayout.setFitsSystemWindows(false);
}
总结:
上面三个方法,涵盖了app在大部分沉浸场景下的状态。在了解了底层实现后,我们也可以轻松在安卓上实现IOS的沉浸效果了,最低版本4.4 kitkat现在已经非常普及,随着MIUI、FlyME相继都升级到5.0、6.0以上,魅蓝、红米等大批国产中低端机型的都可以体验到这种酷炫的效果了。
android状态栏总结的更多相关文章
- Android状态栏颜色修改
android状态栏颜色修改 状态栏颜色的修改在4.4和5.x环境下分别有不同的方式,低于4.4以下是不能修改的. 5.x环境下 方式一,状态栏将显示为纯净的颜色,没有渐变效果 /** * 状 ...
- Android状态栏透明(沉浸式效果)
Android状态栏透明(沉浸式效果) 默认效果 沉浸式效果 方式一 源码 下载地址(Android Studio工程):http://download.csdn.net/detail/q487880 ...
- Android状态栏着色
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 状态栏着色,也就是我们经常听到的沉浸式状态栏,关于沉浸式的称呼网上也有很多吐槽的,这里就不做过多讨论了,以下我们统称状态栏着色,这样 ...
- android状态栏和NavigationBar的动态控制显示
项目在开发阅读器,阅读器对阅读界面的要求就是在工具栏不显示的状态下,ActionBar和NavigationBar都是不显示的,当工具栏显示时它们都出来,这就需要动态控制它们的显示与隐藏. 第一阶段: ...
- [Android] 状态栏的一些认识
前段时间遇到几个关于状态栏的问题,又了解了一下状态栏相关的知识,现在做一下记录. 本文地址:http://www.cnblogs.com/rossoneri/p/4316343.html 前戏和问题 ...
- Translucent Bar Android状态栏自定义颜色
Android4.4 一个很重要的改变就是透明系统栏..新的系统栏是渐变透明的, 可以最大限度的允许屏幕显示更多内容, 也可以让系统栏和 Action Bar 融为一体, 仅仅留下最低限度的背景保护以 ...
- Android状态栏微技巧,带你真正意义上的沉浸式
记得之前有朋友在留言里让我写一篇关于沉浸式状态栏的文章,正巧我确实有这个打算,那么本篇就给大家带来一次沉浸式状态栏的微技巧讲解. 其实说到沉浸式状态栏这个名字我也是感到很无奈,真不知道这种叫法是谁先发 ...
- 获取Android状态栏高度的屡试不爽的方法
文本转载于:http://blog.csdn.net/yinkai1205/article/details/8638864 如下代码所示: [java] view plaincopy private ...
- Android——状态栏通知栏Notification
1.AndroidManifest.xml注意要同时注册Notification02Activity <!-- 状态通知栏 Notification --> <acti ...
- android 状态栏、标题栏、屏幕高度
1.获取状态栏高度: decorView是window中的最顶层view,可以从window中获取到decorView,然后decorView有个getWindowVisibleDisplayFram ...
随机推荐
- jmeter switch controller
工作方式: Switch控制器通过给该控制器中的Value赋值,来指定运行哪个采样器.有两种赋值方式: 1.第一种是数值,Switch控制器下的子节点从0开始计数,通过指定子节点所在的数值来确定执行哪 ...
- python基础学习笔记—— 多继承
本节主要内容: 1.python多继承 2.python经典类的MRO 3.python新式类的MRO.C3算法 4.super是什么鬼? 一.python多继承 在前⾯的学习过程中. 我们已经知道了 ...
- 光学字符识别OCR-3
连通性 可以看到,每一层的图像是由若干连通区域组成的,文字本身是由笔画较为密集组成的,因此往往文字也能够组成一个连通区域.这里的连通定义为 8邻接,即某个像素周围的8个像素都定义为邻接像素,邻接的像素 ...
- python常用方法总结
1.os模块的路径拼接: import os now_path=os.path.abspath(__file__)#当前运行文件的路径 print(now_path) uppeer_path=os.p ...
- Python 协程、IO模型
1.协程(单线程实现并发)2.I/0模型 2.1阻塞I/O 2.2非阻塞I/O 知识点一:协程 协程的目的:是想要在单线程下实现并发(并发看起来是同时运行的) 并发=多个任务间切换+保存状态(正常情况 ...
- php默认有最大执行时间
执行php默认有最大执行时间,默认30s,修改,不能设置’1h’,貌似单位不能修改
- 如何杀死linux-zombie僵尸进程
百科: ZOMBIE:僵尸状态,表示进程结束但尚未消亡的一种状态,此时进程已经结束运行并释放大部分资源,但尚未释放进程控制块. 与ZOMBIE对应的进程状态还有RUNNING(正在运行或等待运行状态) ...
- Linux Shell系列教程之(四)Shell注释
本文是Linux Shell系列教程的第(四)篇,更多shell教程请看:Linux Shell系列教程 与许多的编程语言一样,Shell中也有注释符号,今天就为大家来介绍下Shell中的注释的语法及 ...
- 【bzoj1014】[JSOI2008]火星人prefix Splay+Hash+二分
题目描述 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 ...
- centos中代理的设置
最近在校园网中使用一个centos的主机,链接网络是需要代理的,如果是windows主机在Internet选项里设置一下就可以,可是在linux这个任何配置都要更改配置文件的系统里我还真是纠结了好大一 ...