状态栏 导航栏 全屏 安全区域 属性设置总结

1,306 阅读4分钟

1.setSystemUiVisibility()

int flag =
        View.SYSTEM_UI_FLAG_HIDE_NAVIGATION //隐藏导航栏
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION//不隐藏导航的情况下,将Activity的显示范围扩展到导航栏底部,但是Activity的底部内容会被遮挡.
                | View.SYSTEM_UI_FLAG_FULLSCREEN//隐藏状态栏 如果需要一直隐藏  可以使用WindowManager.LayoutParams.FLAG_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN//不隐藏状态栏的情况下 将Activity内容显示在状态栏下 ,但是内容会被遮挡
                | View.SYSTEM_UI_FLAG_IMMERSIVE//避免用户交互导致清楚全屏状态,配合全屏时使用
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY//避免某些⽤户交互造成系统⾃动清除全屏状态。同时Activity的部分内容也因此被StatusBar覆盖遮挡。
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE//稳定布局,在动态显示隐藏 状态栏导航栏的情况下,系统为设置了fitSysetmWindow=true的View固定Padding值.使内容不上下移动
        ;
getWindow().getDecorView().setSystemUiVisibility(flag);

2.fitSystemWindow

只有个设置了View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 或者View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 时 fitSystemWindow=true才有效

3.WindowManager属性

1. WindowManager.FLAG_TRANSLUCENT_STATUS 设置状态栏透明

会自动设置 View.SYSTEM_UI_FLAG_LAYOUT_STABLE和SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

2. WindowManager.FLAG_FULLSCREEN 隐藏状态栏, 会忽略输入法的SOFT_INPUT_ADJUST_RESIZE

3. WindowManager.FLAG_TRANSLUCENT_NAVIGATION 半透明导航栏

会自动设置View.SYSTEM_UI_FLAG_LAYOUT_STABLE和View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

4. WindowManager.FLAG_DRAWS_SYSTEM_BAR_VACKGROUNDS为导航栏和状态栏设置背景颜色

将导航栏状态栏设置透明色,并且将所在的空间设置成window.getStatusBarColor()和window.getNavigationBarColor() 的颜色

5.使用SOFT_INPUT_ADJUST_RESIZE

同时View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN或View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION时,当键盘弹出时,只会tSystemWindow=true的view所占区域会被resize,其他view将会被软键盘覆盖。

4.安全区域下显示内容

public static void setDisplayCutoutShortEdges(Window window) {
  if (window == null) {
      return;
  }

  // LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES 才可以使用刘海区显示
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
      WindowManager.LayoutParams lp = window.getAttributes();
      // 应用如果想让布局延伸到刘海区显示,设置 LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES属性使用刘海区显示
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
          lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
      }else{
          lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
      }
      window.setAttributes(lp);
  }
}

4.设置全屏模式代码

下面代码可以设置 1-2-3步骤展示全屏 也可以设置 1-4步骤展示全屏


1. //安全区域下显示内容
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
  WindowManager.LayoutParams lp = getWindow().getAttributes();
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
      lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
  }else{
      lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
  }
  getWindow().setAttributes(lp);
}
2. //全屏模式
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

3.  //全屏模式如果不设置上面的WindowManager.LayoutParams.FLAG_FULLSCREEN 用户交互会退出全屏
int flag =
      View.SYSTEM_UI_FLAG_FULLSCREEN |//隐藏状态栏 如果需要一直隐藏  可以使用WindowManager.LayoutParams.FLAG_FULLSCREEN
              View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | //隐藏导航栏
              View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |//不隐藏状态栏的情况下 将Activity内容显示在状态栏下 ,但是内容会被遮挡
              View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |//不隐藏导航的情况下,将Activity的显示范围扩展到导航栏底部,但是Activity的底部内容会被遮挡.
              View.SYSTEM_UI_FLAG_LAYOUT_STABLE  //稳定布局,在动态显示隐藏 状态栏导航栏的情况下,系统为设置了fitSysetmWindow=true的View固定Padding值.使内容不上下移动

      ;

4.  
int flag =
      View.SYSTEM_UI_FLAG_FULLSCREEN |//隐藏状态栏 如果需要一直隐藏  可以使用WindowManager.LayoutParams.FLAG_FULLSCREEN
              View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | //隐藏导航栏
              View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |//不隐藏状态栏的情况下 将Activity内容显示在状态栏下 ,但是内容会被遮挡
              View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |//不隐藏导航的情况下,将Activity的显示范围扩展到导航栏底部,但是Activity的底部内容会被遮挡.
              View.SYSTEM_UI_FLAG_LAYOUT_STABLE  //稳定布局,在动态显示隐藏 状态栏导航栏的情况下,系统为设置了fitSysetmWindow=true的View固定Padding值.使内容不上下移动
             //用户windowmanger m没有设置全屏状态下不设置下面两个flag 会交互导致退出全屏,需要加下边的flag 保证不退出全屏
             View.SYSTEM_UI_FLAG_IMMERSIVE//避免用户交互导致清楚全屏状态,配合全屏时使用
             | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY//避免某些⽤户交互造成系统⾃动清除全屏状态。同时Activity的部分内容也因此被StatusBar覆盖遮挡。

      ;
  

5. 修改状态栏导航栏颜色



getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS|WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().setStatusBarColor(Color.RED);
getWindow().setNavigationBarColor(Color.GREEN);

6.设置状态栏导航栏字体颜色

12 以上
WindowInsetsControllerCompat controller = ViewCompat.getWindowInsetsController(activity.getWindow().getDecorView());
if (controller != null) {
   double v = ColorUtils.calculateLuminance(xxxx);
   //状态栏字体色
   controller.setAppearanceLightStatusBars(v>0.5f);
   //导航栏字体色
   controller.setAppearanceLightNavigationBars(v>0.5f);
   controller.show(WindowInsetsCompat.Type.statusBars()|WindowInsetsCompat.Type.navigationBars());
   controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_DEFAULT);
}
double v = ColorUtils.calculateLuminance(xxxxx);

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
   if (v>0.5f){
      newVis = newVis | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
     getWindow().getDecoview().setSystemUiVisibility(newVis)
   }
}

7.显示/隐藏导航栏状态栏

androidR 以上可以使用

      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {

            getWindow().setDecorFitsSystemWindows(true);
            WindowInsetsController controller = getWindow().getInsetsController();
            if (controller != null) {
                controller.show(WindowInsets.Type.statusBars());
                controller.show(WindowInsets.Type.navigationBars());
                controller.show(WindowInsets.Type.systemBars());
//
                controller.hide(WindowInsets.Type.statusBars());
                controller.hide(WindowInsets.Type.navigationBars());
                controller.hide(WindowInsets.Type.systemBars());
                //这块还可以设置BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE,设置画这个之后 左滑返回需要两次才能响应退出页面
                controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_DEFAULT);
            }
        }

其他版本可以参考# setSystemUiVisibility 使用方式.

8. 安全区域的位置获取

主要是摄像头的位置

public static void checkScreenSafeArea(Window window, final View decorView) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {

        decorView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
            @Override
            public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
             
                DisplayCutout cutout = windowInsets.getDisplayCutout();
                if (cutout != null) {
                    // Rect 非功能区域 可以是多个 一般是只有一个
                    List<Rect> list = cutout.getBoundingRects();
                    if (list != null && !list.isEmpty()) {
                        Rect rect = list.get(0);
                        if (rect != null) {
                            int height = rect.height();
                            //可以根据Rect 的left right 判断安全区域的大概位置,再结合分屏以及浮窗模式判断是否需要在此区域内显示内容
                        }
                    }
                }
         
                return windowInsets;
            }
        });
    }
}