From 50c8e973f067d4ef1fc3c2eddd360a0709828968 Mon Sep 17 00:00:00 2001 From: Kuba Holuj Date: Mon, 31 Jan 2022 11:31:27 -0800 Subject: [PATCH] Update StatusBar for Android 11+ (#32975) Summary: Android 11 (API 30) introduced a new interface for changing the appearance of the status bars with [`WindowInsetsController#setSystemBarsAppearance`](https://developer.android.com/reference/kotlin/android/view/WindowInsetsController#setsystembarsappearance) and deprecated using the `WindowManager#systemUiVisibility` properties. Apparently, once you call `setSystemBarsAppearance` Android will no longer respect `systemUiVisibility` and if anyone, such as the Android 12 Splash Screen library, happens to call it, it will break status bars. This PR augments the RN StatusBarModule to use the new interface on Android 11+. Also updated the rn-tester app, see video. https://user-images.githubusercontent.com/1124321/151321561-8202e237-cf7d-45ce-b957-18b5bafd17c4.mov ## Changelog [Android] [Changed] - Use new StatusBar API on Android 11 (API 30)+ Pull Request resolved: https://github.com/facebook/react-native/pull/32975 Reviewed By: cortinico Differential Revision: D33814853 Pulled By: ShikaSD fbshipit-source-id: c0f2651015dddb4871a3e3b26642f76a46da2a76 --- .../modules/statusbar/StatusBarModule.java | 28 ++++++++---- .../js/examples/StatusBar/StatusBarExample.js | 43 +++++++++++++++++-- 2 files changed, 60 insertions(+), 11 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.java index e8dc15272e9..a3beef47e71 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.java @@ -15,6 +15,7 @@ import android.content.Context; import android.os.Build; import android.view.View; import android.view.WindowInsets; +import android.view.WindowInsetsController; import android.view.WindowManager; import androidx.annotation.Nullable; import androidx.core.view.ViewCompat; @@ -184,12 +185,23 @@ public class StatusBarModule extends NativeStatusBarManagerAndroidSpec { return; } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - UiThreadUtil.runOnUiThread( - new Runnable() { - @TargetApi(Build.VERSION_CODES.M) - @Override - public void run() { + UiThreadUtil.runOnUiThread( + new Runnable() { + @TargetApi(Build.VERSION_CODES.R) + @Override + public void run() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + WindowInsetsController insetsController = activity.getWindow().getInsetsController(); + if ("dark-content".equals(style)) { + // dark-content means dark icons on a light status bar + insetsController.setSystemBarsAppearance( + WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS, + WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS); + } else { + insetsController.setSystemBarsAppearance( + 0, WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS); + } + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { View decorView = activity.getWindow().getDecorView(); int systemUiVisibilityFlags = decorView.getSystemUiVisibility(); if ("dark-content".equals(style)) { @@ -199,7 +211,7 @@ public class StatusBarModule extends NativeStatusBarManagerAndroidSpec { } decorView.setSystemUiVisibility(systemUiVisibilityFlags); } - }); - } + } + }); } } diff --git a/packages/rn-tester/js/examples/StatusBar/StatusBarExample.js b/packages/rn-tester/js/examples/StatusBar/StatusBarExample.js index 5db186500b8..452e04e1d14 100644 --- a/packages/rn-tester/js/examples/StatusBar/StatusBarExample.js +++ b/packages/rn-tester/js/examples/StatusBar/StatusBarExample.js @@ -23,7 +23,7 @@ const { const colors = ['#ff0000', '#00ff00', '#0000ff', 'rgba(0, 0, 0, 0.4)']; -const barStyles = ['default', 'light-content']; +const barStyles = ['default', 'light-content', 'dark-content']; const showHideTransitions = ['fade', 'slide']; @@ -129,11 +129,16 @@ class StatusBarStyleExample extends React.Component<{...}, $FlowFixMeState> { style: '{getValue(barStyles, this._barStyleIndex)}' + + (default is dark for iOS, light for Android) + - animated: {this.state.animated ? 'true' : 'false'} + + animated (ios only): {this.state.animated ? 'true' : 'false'} + @@ -288,6 +293,9 @@ class StatusBarStaticIOSExample extends React.Component<{...}> { setBarStyle('default', true) + + (default is dark for iOS, light for Android) + { @@ -342,6 +350,36 @@ class StatusBarStaticAndroidExample extends React.Component<{...}> { setHidden(false) + { + StatusBar.setBarStyle('light-content'); + }}> + + setBarStyle('light-content') + + + { + StatusBar.setBarStyle('dark-content'); + }}> + + setBarStyle('dark-content') + + + { + StatusBar.setBarStyle('default'); + }}> + + setBarStyle('default') + + + + (default is dark for iOS, light for Android) + { @@ -448,7 +486,6 @@ exports.examples = [ render(): React.Node { return ; }, - platform: 'ios', }, { title: 'StatusBar network activity indicator',