android状态栏总结

  1. 针对状态栏的操作,只针对4.4kitKat(含)以上的机型,部分国产rom会失效,目前发现的有华为的EMUI
  2. Activity必须是noActionbar主题
  3. 本文基于StatusBarUtils略作修改,感谢作者laobie
  4. 本文源码地址
相关属性重温
  • FitsSystemWindows
    在使用FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDSFLAG_TRANSLUCENT_STATUS挤占了状态栏的高度的时候,我们的布局文件也跟着顶到了状态栏上。通过FitsSystemWindows,系统会把app布局文件的paddingTop修改成状态栏的高度,达到适配的效果

    false顶到状态栏

true,paddingTop有一个状态栏高度

  • 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的组织层级如下,

noActionbarView层次.png

为什么嵌套那么深,因为各个层次可能都会有几个ViewStub方便注入,只是我们现在的主题用不到就是空了。

下面开始实战了,一般我们用的比较多的是透明状态栏、设置状态栏颜色、DrawerLayout盖在状态栏上三种。

1. 透明状态栏

这种情况一般用于把图片延伸到状态栏上,图片还分两种

  1. 作为background的全屏大图
  2. 作为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。从而让图片延伸到了状态栏

不透明状态栏.png

透明状态栏.png

这种情况下,对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);
}

app内容布局有了padding.png

注意!!要延伸到状态栏的图片,如果不是根节点的背景图,而是一个ImageView控件,那么就不能设置setFitsSystemWindows了,原因参考上图红框。这种情况下,为了防止顶到状态栏,需要手动在xml里通过paddingTopmarginTop调整标题栏元素位置达到适配。类似下图

延伸到状态栏的图片是一个ImageView

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步

  1. 插入纯色控件到内容View(如果不是LinarLayout需要考虑内容View元素重新排列)
  2. 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以上,魅蓝、红米等大批国产中低端机型的都可以体验到这种酷炫的效果了。

时间: 2024-10-06 01:16:22

android状态栏总结的相关文章

获取Android状态栏高度的屡试不爽的方法

如下代码所示: [java] view plaincopy private int getStatusBarHeight() { Class<?> c = null; Object obj = null; Field field = null; int x = 0, sbar = 0; try { c = Class.forName("com.android.internal.R$dimen"); obj = c.newInstance(); field = c.getFi

Android状态栏透明(沉浸式效果)

Android状态栏透明(沉浸式效果) 默认效果 沉浸式效果 方式一 源码 下载地址(Android Studio工程):http://download.csdn.net/detail/q4878802/9058275 1. 修改状态栏和导航栏的属性为透明 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { //透明状态栏 getWindow().addFlags(WindowManager.LayoutParams.FLAG_T

Android状态栏着色

版权声明:本文为博主原创文章,未经博主允许不得转载. 前言 状态栏着色,也就是我们经常听到的沉浸式状态栏,关于沉浸式的称呼网上也有很多吐槽的,这里就不做过多讨论了,以下我们统称状态栏着色,这样我觉得更加容易理解. 从Android4.4开始,才可以实现状态栏着色,并且从5.0开始系统更加完善了这一功能,可直接在主题中设置<item name="colorPrimaryDark">@color/colorPrimaryDark</item>或者getWindow(

android 状态栏操作

最近太忙了.好长时间没动博客,把原来的东西拿出来都重新温习下. private void collapseStatusBar() { int currentApiVersion = android.os.Build.VERSION.SDK_INT; try { Object service = getSystemService("statusbar"); Class<?> statusbarManager = Class .forName("android.app

android 状态栏(StatusBar)

一.SystemUI 概述 自 android2.2 开始 , 原本存在与 framework-res.apk 中的状态栏和下拉通知栏界面控制被分割出一个单独的 apk 文件 , 命名为 SystemUI.apk, 保存在 System/app 文件夹中.在 SystemUI.apk 中 , 是存在着状态栏的图标 ,XML 和控制文件等 , 这样的分割 , 使我们可以更方便地去修改. SystemUI 模块中主要包含了 USB 和 Statusbar 两个子模块,本文将以 Statusbar 为

Android -- 状态栏高度

干货 Class<?> c = null; Object obj = null; Field field = null; int x = 0, sbar = 0; try { c = Class.forName("com.android.internal.R$dimen"); obj = c.newInstance(); field = c.getField("status_bar_height"); x = Integer.parseInt(field

十分钟设置android状态栏一体化开源工程推荐

1.前言 在android kitkat 有一个新的特性可以设置手机状态栏的背景,让手机整个界面的风格保持一致,看起来非常清爽,在今年的google i/o上的android l默认就是这种风格.来现在看我们怎么加上这个酷黑狂拽掉渣天的功能怎么给我们的程序加上.来先看一下demo效果图. 2.关与kitkat android 4.4 提供了一套能透明的系统ui样式给状态栏和导航栏,这样的话就不用向以前那样每天面对着黑乎乎的上下两条黑栏了,还可以调成跟activity 一样的样式,形成一个完整的主

Android状态栏微技巧,带你真正理解沉浸式模式

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/51763825 本文同步发表于我的微信公众号,扫一扫文章底部的二维码或在微信搜索 郭霖 即可关注,每天都有文章更新. 记得之前有朋友在留言里让我写一篇关于沉浸式状态栏的文章,正巧我确实有这个打算,那么本篇就给大家带来一次沉浸式状态栏的微技巧讲解. 其实说到沉浸式状态栏这个名字我也是感到很无奈,真不知道这种叫法是谁先发起的.因为Android官方从来没有给出过沉浸式状态栏这样的命名,

Android 状态栏那些小坑?

背景:因为之前老板上次问我我们的app能不能自定义上面的状态栏我说可以啊!当时没管,今天试了下果然很多坑,之前github上也有很多大佬写了一个开源库有兴趣的可以点进去看下支持DrawLayout沉侵式[StatusBarUtil](https://github.com/laobie/StatusBarUtil)感觉好牛逼,像大佬敬礼,我毕竟是个小喽喽,我只能用最蠢的办法! 首先说下关于状态栏当系统版本为4.4或者4.4以上时可以使用沉浸式状态栏实现代码 其实状态栏这东西不是很难,就是通过添加一