最近项目组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)