沉浸式状态栏和透明状态栏

前言

一般手机的界面上都会有:状态栏、标题栏、导航栏等固定的布局;


样式图

区别

  • 沉浸式状态栏:这种样式其实就是把状态栏、标题栏、导航栏都去掉,让整个屏幕都只显示应用要显示的界面,从而给用户一种“沉浸”在里面的感觉!


    效果图1

    效果图2
  • 透明状态栏:这种样式其实就是把状态栏和标题栏配置成一种颜色,达到一种美观效果!


    效果图
透明状态栏

4.4版本一下没办法配置透明栏,4.4、5.0、6.0不同版本又会有不同的效果,所以我们要做好适配工作

实现步骤
  • 去掉系统自带的标题栏,采用自定义的状态栏(自定义状态栏推荐使用Toolbar)

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

  • 设置状态栏为透明
    • 第一种方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
      getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  }
  super.onCreate(savedInstanceState);
}
  • 第二种方法:

使用android:windowTranslucentStatus属性需要在res目录下新建values-v19文件夹,style文件要放在里面。

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
      <item name="android:windowTranslucentStatus">true</item>
</style>
  • 防止状态栏和自定义标题栏重合
    • 第一种方法:
      在Activity的根布局文件中添加

android:fitsSystemWindows="true"
```

  • 第二种方法:

给在Toolbar的上方添加一个和状态栏高度一样的Veiw,并将这个View的背景色设置成和Toolbar的背景色一样。也可以直接给Toobar设置paddingTop等于状态栏高。

public static void setToolBarPaddingHeight(Window window, View view) {
      //TODO: 代码设置标题栏paddingtop为状态栏的高
      int statusBarHeight = getStatusBarHeight(window.getContext());
      view.setPadding(view.getPaddingLeft(), view.getPaddingTop() + statusBarHeight, view.getPaddingRight(), view.getPaddingBottom());
  }
public static int getStatusBarHeight(Context context) {
      //TODO: 算取状态栏的高
      int result = 0;
      int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
      if (resourceId > 0) {
          result = context.getResources().getDimensionPixelSize(resourceId);
      }
      return result;
  }

通过以上就可以实现透明状态栏了。总的来说还是比较简单的,下面贴一下只用代码就可以实现透明状态栏的工具类!

/**
* Created by ML on 2017/3/9.
* 前言:
* 在Android4.4之前,我们的应用没法改变手机的状态栏颜色,google在Android4.4以后提供了设置状态栏的方法;
* 沉浸式状态栏和透明式状态栏是不同的概念;
*/

public class UIUtils {
   //TODO: 透明状态栏相关方法
   /**
    * 相关Flag
    WindowManager.LayoutParams.FLAG_FULLSCREEN
    隐藏状态栏

    View.SYSTEM_UI_FLAG_VISIBLE API 14
    默认标记

    View.SYSTEM_UI_FLAG_LOW_PROFILE API 14
    低调模式, 会隐藏不重要的状态栏图标

    View.SYSTEM_UI_FLAG_LAYOUT_STABLE API 16
    保持整个View稳定, 常和控制System UI悬浮, 隐藏的Flags共用, 使View不会因为System UI的变化而重新layout

    View.SYSTEM_UI_FLAG_FULLSCREEN API 16
    状态栏隐藏,效果同设置WindowManager.LayoutParams.FLAG_FULLSCREEN

    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN API 16
    视图延伸至状态栏区域,状态栏上浮于视图之上

    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION API 14
    隐藏导航栏

    View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION API 16
    视图延伸至导航栏区域,导航栏上浮于视图之上

    View.SYSTEM_UI_FLAG_IMMERSIVE API 19
    沉浸模式, 隐藏状态栏和导航栏, 并且在第一次会弹泡提醒, 并且在状态栏区域滑动可以呼出状态栏(这样会系统会清楚之前设置的View.SYSTEM_UI_FLAG_FULLSCREEN或View.SYSTEM_UI_FLAG_HIDE_NAVIGATION标志)。使之生效,需要和View.SYSTEM_UI_FLAG_FULLSCREEN,View.SYSTEM_UI_FLAG_HIDE_NAVIGATION中的一个或两个同时设置。

    View.SYSTEM_UI_FLAG_IMMERSIVE_STIKY API 19
    与上面唯一的区别是, 呼出隐藏的状态栏后不会清除之前设置的View.SYSTEM_UI_FLAG_FULLSCREEN或View.SYSTEM_UI_FLAG_HIDE_NAVIGATION标志,在一段时间后将再次隐藏系统栏)
    */

   /**
    * 实现透明状态栏且不需要配置android:fitsSystemWindows="true"
    * 注意::标题栏根布局高度必须是自适应
    *
    * @param window
    * @param view   标题栏根布局(根布局高度必须是自适应)
    */
   public static void setScreenTranslucentStatus(Window window, int Color, View view) {
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
           setTranslucentStatusForSDK_LOLLIPOP(window, Color);
       } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
           setTranslucentStatusForSDK_KITKAT(window);
       }
       setToolBarPaddingHeight(window, view);
   }

   /**
    * 实现透明状态栏需要配置android:fitsSystemWindows="true"
    * 注意::标题栏根布局高度必须是自适应
    *
    * @param window
    */
   public static void setTranslucentStatusXML(Window window, int color) {
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
           setTranslucentStatusForSDK_LOLLIPOP(window, color);
       } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
           setTranslucentStatusForSDK_KITKAT(window);
       }
   }

   /**
    * 设置Android状态栏的字体颜色,状态栏为亮色的时候字体和图标是黑色,状态栏为暗色的时候字体和图标为白色
    *
    * @param dark 状态栏字体和图标是否为深色
    */
   public static void setStatusBarFontDark(@NonNull Window window, @NonNull boolean dark, int color, View view) {
       //TODO: 实现状态栏白底黑字
       if (PhoneUtil.isMIUI()) {
           setMIUIBarFontDark(window, dark, view);
       } else if (PhoneUtil.isFlyme()) {
           setFlymeBarFontDark(window, dark, view);
       } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
           setSDK_MBarFontDark(window, dark, view);
       } else {
           L.i("Android原生6.0一下系统>>>>>>>>>>>>>>>实现状态栏灰底白字");
           setToolBarBgColor(window, color, view);
       }
   }

   public static void setSDK_MBarFontDark(@NonNull Window window, @NonNull boolean dark, View view) {
       //TODO: 配置Android原生6.0系统状态栏白底黑字
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
           if (dark) {
               setScreenTranslucentStatus(window, Color.TRANSPARENT, view);
               window.getDecorView().setSystemUiVisibility(
                       View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                               | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
               L.i("Android原生6.0系统>>>>>>>>>>>>>>>状态栏白底黑字");
           }
       }
   }

   public static void setFlymeBarFontDark(@NonNull Window window, @NonNull boolean dark, View view) {
       //TODO: 配置魅族系统状态栏白底黑字
       try {
           setScreenTranslucentStatus(window, Color.TRANSPARENT, view);
           WindowManager.LayoutParams lp = window.getAttributes();
           Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
           Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
           darkFlag.setAccessible(true);
           meizuFlags.setAccessible(true);
           int bit = darkFlag.getInt(null);
           int value = meizuFlags.getInt(lp);
           if (dark) {
               value |= bit;
           } else {
               value &= ~bit;
           }
           meizuFlags.setInt(lp, value);
           window.setAttributes(lp);
           L.i("小米系统>>>>>>>>>>>>>>>状态栏白底黑字");
       } catch (Exception e) {
           e.printStackTrace();
       }
   }

   public static void setMIUIBarFontDark(@NonNull Window window, @NonNull boolean dark, View view) {
       //TODO: 配置小米系统状态栏白底黑字
       try {
           setScreenTranslucentStatus(window, Color.TRANSPARENT, view);
           Class clazz = window.getClass();
           Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
           Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
           int darkModeFlag = field.getInt(layoutParams);
           Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
           if (dark) {    //状态栏亮色且黑色字体
               extraFlagField.invoke(window, darkModeFlag, darkModeFlag);
           } else {       //清除黑色字体
               extraFlagField.invoke(window, 0, darkModeFlag);
           }
           L.i("小米系统>>>>>>>>>>>>>>>状态栏白底黑字");
       } catch (Exception e) {
           e.printStackTrace();
       }
   }

   public static void setToolBarBgColor(Window window, int color, View view) {
       //TODO: Android原生5.0一下系统实现灰底白字
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
           setTranslucentStatusForSDK_LOLLIPOP(window, color);
           setToolBarPaddingHeight(window, view);
       } else {
           //            setTranslucentStatusForSDK_KITKAT(window);
           L.i("Android原生4.4以上5.0一下系统需要自己手动在状态栏加view实现灰底白字(//www.greatytc.com/p/a44c119d6ef7)");
       }
   }

   public static void setToolBarPaddingHeight(Window window, View view) {
       //TODO: 代码设置标题栏paddingtop为状态栏的高
       int statusBarHeight = getStatusBarHeight(window.getContext());
       view.setPadding(view.getPaddingLeft(), view.getPaddingTop() + statusBarHeight, view.getPaddingRight(), view.getPaddingBottom());
   }

   public static void setTranslucentStatusForSDK_KITKAT(Window window) {
       //TODO: 4.4以上系统状态栏透明
       window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
   }

   public static void setTranslucentStatusForSDK_LOLLIPOP(Window window, int Color) {
       //TODO:  5.0以上系统状态栏透明
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
           window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
           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);  //TODO: 指定状态栏的颜色和布局的颜色相同
       }
   }

   public static int getStatusBarHeight(Context context) {
       //TODO: 算取状态栏的高
       int result = 0;
       int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
       if (resourceId > 0) {
           result = context.getResources().getDimensionPixelSize(resourceId);
       }
       return result;
    }
   ```
#### 沉浸式状态栏


重写Activity的onWindowFocusChanged()方法,然后加入如下逻辑即可:

@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus && Build.VERSION.SDK_INT >= 19) {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}


[参考文章1](http://blog.csdn.net/xuchao_blog/article/details/54693482)
[参考文章2](//www.greatytc.com/p/a44c119d6ef7)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,188评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,464评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,562评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,893评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,917评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,708评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,430评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,342评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,801评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,976评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,115评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,804评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,458评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,008评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,135评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,365评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,055评论 2 355

推荐阅读更多精彩内容