react ntive StatusBar.setTranslucent();

最近项目组code review让查看StatusBar.setTranslucent()这个方法到底是干嘛的,就看了下源码;
在android中查到的代码是

@ReactMethod
  public void setTranslucent(final boolean translucent) {
    final Activity activity = getCurrentActivity();
    if (activity == null) {
      FLog.w(ReactConstants.TAG, "StatusBarModule: Ignored status bar change, current activity is null.");
      return;
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      UiThreadUtil.runOnUiThread(
        new GuardedRunnable(getReactApplicationContext()) {
          @TargetApi(Build.VERSION_CODES.LOLLIPOP)
          @Override
          public void runGuarded() {
            // If the status bar is translucent hook into the window insets calculations
            // and consume all the top insets so no padding will be added under the status bar.
            View decorView = activity.getWindow().getDecorView();
            if (translucent) {
              decorView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
                @Override
                public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
                  WindowInsets defaultInsets = v.onApplyWindowInsets(insets);
                  return defaultInsets.replaceSystemWindowInsets(
                    defaultInsets.getSystemWindowInsetLeft(),
                    0,
                    defaultInsets.getSystemWindowInsetRight(),
                    defaultInsets.getSystemWindowInsetBottom());
                }
              });
            } else {
              decorView.setOnApplyWindowInsetsListener(null);
            }

            ViewCompat.requestApplyInsets(decorView);
          }
        });
    }
  }

核心代码是onApplyWindowInsets,查过文档了,它主要是设置跟视图的视图大小,代码中设置top为0标明 我们如果在StatusBar.setTranslucent()中传true,会让布局文件顶在decorview最顶部,即会被状态栏覆盖(视图全屏,但是视图顶部会被statusbar覆盖),如果传false则不做处理;
下面贴一张别人画的图来显示:
https://blog.csdn.net/weixin_34007879/article/details/87443273
在这里插入图片描述

另外和它相关的是
StatusBar.setBackgroundColor(’#FFFFFF’);
对映的原生方法是:

@ReactMethod
  public void setColor(final int color, final boolean animated) {
    final Activity activity = getCurrentActivity();
    if (activity == null) {
      FLog.w(ReactConstants.TAG, "StatusBarModule: Ignored status bar change, current activity is null.");
      return;
    }

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

      UiThreadUtil.runOnUiThread(
          new GuardedRunnable(getReactApplicationContext()) {
            @TargetApi(Build.VERSION_CODES.LOLLIPOP)
            @Override
            public void runGuarded() {
              activity
                  .getWindow()
                  .addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
              if (animated) {
                int curColor = activity.getWindow().getStatusBarColor();
                ValueAnimator colorAnimation =
                    ValueAnimator.ofObject(new ArgbEvaluator(), curColor, color);

                colorAnimation.addUpdateListener(
                    new ValueAnimator.AnimatorUpdateListener() {
                      @Override
                      public void onAnimationUpdate(ValueAnimator animator) {
                        activity
                            .getWindow()
                            .setStatusBarColor((Integer) animator.getAnimatedValue());
                      }
                    });
                colorAnimation.setDuration(300).setStartDelay(0);
                colorAnimation.start();
              } else {
                activity.getWindow().setStatusBarColor(color);
              }
            }
          });
    }
  }

上面核心代码activity.getWindow().setStatusBarColor(color); 只是设置statusbar的颜色;

另外我们的项目中已经在基类activity中强制设置了全屏透明状态栏(window.setStatusBarColor(Color.TRANSPARENT)),就是说 如果rn端不做任何处理,正式rn视图默认全屏,并且statusbar是透明的,我们项目中之所以页面statusbar没有透明,是因为项目中用了react-navigation,react-navigation会统一处理头部的导航栏;
参考代码:

 public void setStatusBarColor(Window window, int color) {
            //取消设置透明状态栏,使 ContentView 内容不再覆盖状态栏
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            //需要设置这个 flag 才能调用 setStatusBarColor 来设置状态栏颜色
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            //设置状态栏颜色
            window.setStatusBarColor(color);
            //设置导航栏颜色
            window.setNavigationBarColor(Color.BLACK);
 }


public void setLightStatusBar(Window window, boolean lightStatusBar) {
            // 设置浅色状态栏时的界面显示
            View decor = window.getDecorView();
            int ui = decor.getSystemUiVisibility();
            if (lightStatusBar) {
                ui |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            } else {
                ui &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            }
            decor.setSystemUiVisibility(ui);
}

最后项目建议,因为activity容器都做了处理react-navigation也做了处理,建议去除工程中所有对statusbar的设置(StatusBar.setTranslucent和statusBarStyle),目前自己的测试机试了没问题,但是还没有找到有问题的手机来测试,代码先不推了,找到手机试试再推;(注意购物车中设置modal弹层setBackgroundColor的要保留,这个是专门解决一个bug的,bug原因是用了react-navigation的头部 无法让modal遮盖住statusbar)

发布了15 篇原创文章 · 获赞 4 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/wwl901215/article/details/88865221