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

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://github.com/facebook/react-native/wiki/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
This commit is contained in:
Kuba Holuj 2022-01-31 11:31:27 -08:00 коммит произвёл Facebook GitHub Bot
Родитель c1bb945277
Коммит 50c8e973f0
2 изменённых файлов: 60 добавлений и 11 удалений

Просмотреть файл

@ -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);
}
});
}
}
});
}
}

Просмотреть файл

@ -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> {
<Text>style: '{getValue(barStyles, this._barStyleIndex)}'</Text>
</View>
</TouchableHighlight>
<View style={styles.wrapper}>
<Text>(default is dark for iOS, light for Android)</Text>
</View>
<TouchableHighlight
style={styles.wrapper}
onPress={this._onChangeAnimated}>
<View style={styles.button}>
<Text>animated: {this.state.animated ? 'true' : 'false'}</Text>
<Text>
animated (ios only): {this.state.animated ? 'true' : 'false'}
</Text>
</View>
</TouchableHighlight>
</View>
@ -288,6 +293,9 @@ class StatusBarStaticIOSExample extends React.Component<{...}> {
<Text>setBarStyle('default', true)</Text>
</View>
</TouchableHighlight>
<View style={styles.wrapper}>
<Text>(default is dark for iOS, light for Android)</Text>
</View>
<TouchableHighlight
style={styles.wrapper}
onPress={() => {
@ -342,6 +350,36 @@ class StatusBarStaticAndroidExample extends React.Component<{...}> {
<Text>setHidden(false)</Text>
</View>
</TouchableHighlight>
<TouchableHighlight
style={styles.wrapper}
onPress={() => {
StatusBar.setBarStyle('light-content');
}}>
<View style={styles.button}>
<Text>setBarStyle('light-content')</Text>
</View>
</TouchableHighlight>
<TouchableHighlight
style={styles.wrapper}
onPress={() => {
StatusBar.setBarStyle('dark-content');
}}>
<View style={styles.button}>
<Text>setBarStyle('dark-content')</Text>
</View>
</TouchableHighlight>
<TouchableHighlight
style={styles.wrapper}
onPress={() => {
StatusBar.setBarStyle('default');
}}>
<View style={styles.button}>
<Text>setBarStyle('default')</Text>
</View>
</TouchableHighlight>
<View style={styles.wrapper}>
<Text>(default is dark for iOS, light for Android)</Text>
</View>
<TouchableHighlight
style={styles.wrapper}
onPress={() => {
@ -448,7 +486,6 @@ exports.examples = [
render(): React.Node {
return <StatusBarStyleExample />;
},
platform: 'ios',
},
{
title: 'StatusBar network activity indicator',