沉浸式状态栏简单实现

从实践的角度给出一些沉浸式状态栏的方法,并解决沉浸式带来的问题

本文适用于4.4到更高的系统版本

实现的效果

效果1

效果2

状态栏透明

  1. 使用代码设置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /**
    * 使状态栏透明 android 5.0以上
    * 获取根布局给其添加内容延伸到状态栏标记,并设置状态栏透明色
    */
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public static void transparentStatusBar(Activity activity) {
    View decorView = activity.getWindow().getDecorView();
    int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
    decorView.setSystemUiVisibility(option);
    activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
    }
  2. 修改app主题文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <!-- app主题 -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <!-- 状态栏透明 -->
    <item name="android:windowTranslucentStatus">true</item>
    </style>

状态栏字体颜色

实现图一效果,因为安卓碎片化的原因要分情况处理

  • android6.0以上版本,支持深色模式,可以让状态的文字和图片变成黑色(默认状态栏文字和图片为白色)

    1
    2
    3
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { activity.getWindow().getDecorView()
    .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
    }
  • android6.0以下版本根据品牌系统适配

    1. 小米

      具体可以查看小米开放平台的开发文档

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      if (Build.MANUFACTURER.equals("Xiaomi")) {
      Class<? extends Window> clazz = activity.getWindow().getClass();
      try {
      int darkModeFlag = 0;
      Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
      Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
      darkModeFlag = field.getInt(layoutParams);
      Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
      extraFlagField.invoke(activity.getWindow(), darkModeFlag, darkModeFlag);
      } catch (Exception e) {
      e.printStackTrace();
      }
      }
    2. 魅族

      魅族系统貌似会自动根据界面的背景自己适配状态栏颜色

    3. 其他

      可以去查看对应系统的开发文档

    半透明状态栏

    如果UI妹子不是特别要求透明状态栏的话,可以使用该方式(图2效果)

    其实就是给布局的顶部加一个状态栏大小高度一样的半透明控件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    //设置半透明状态栏
    protected void setHalfStatusBar() {
    //获取状态工具类
    int statusBarHeight = StatusBarUtil.getStatusBarHeight(this);
    if (statusBarHeight > 0) {
    //给根布局加一个和状态栏一样大小高度半透明黑色的状态栏,并放置在顶部
    ViewGroup content = (ViewGroup) findViewById(android.R.id.content);
    View translucentStatusBarView = StatusBarUtil.createTranslucentStatusBarView(this, 56);
    if (translucentStatusBarView != null) {
    content.addView(translucentStatusBarView);
    }
    }
    }
    /**
    * 获取状态栏高度
    *
    * @param context context
    * @return 状态栏高度
    */
    public static int getStatusBarHeight(Context context) {
    // 获得状态栏高度
    int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
    int dimensionPixelSize = context.getResources().getDimensionPixelSize(resourceId);
    if (dimensionPixelSize <= 0) { // 如果为获取不到 就使用xml文件的
    dimensionPixelSize = context.getResources().getDimensionPixelSize(R.dimen.top_bar);
    }
    return dimensionPixelSize;
    }
    /**
    * 创建半透明矩形 View
    * 注意是LinearLayout.LayoutParams,因为默认添加到decorView
    *
    * @param alpha 透明值
    * @return 半透明 View
    */
    public static View createTranslucentStatusBarView(Activity activity, int alpha) {
    // 绘制一个和状态栏一样高的矩形
    View statusBarView = new View(activity);
    LinearLayout.LayoutParams params =
    new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
    statusBarView.setLayoutParams(params);
    statusBarView.setBackgroundColor(Color.argb(alpha, 0, 0, 0));
    return statusBarView;
    }

    带来的问题

    • 布局时会加上状态栏的高度

      解决1:给布局或者第一个控件加上一个状态栏高度的paddingmargin

      解决2:fitSystemWindows调整系统窗口布局以适应你自定义的布局

    • fitSystemWindows带来的输入法问题

      ​ 当给布局加上该属性后,布局会自动添加一个padding让布局的内容在状态栏之下,但是会导致输入弹出遮挡控件或者设置了fitSystemWindows属性的控件被拉伸。

      ​ 大家可以参考网上的办法解决