StatusBar: barStyle support for Android (API 23+)

Summary:
Android (starting from API 23) supports "light status bar", thus it is possible to extend StatusBar and make `barStyle` property work not only for iOS, but also for Android.

This PR introduces one more `barStyle` option `dark-content` in addition to two existing ones (`default` and `light-content`).
Why there are 3 options instead of 2?

Two simple reasons:
1) to make all existing applications fully compatible with these changes;
2) the default status bar on Android is dark with white text and icons, while on iOS it is light with black text and icons on it. Thus the `default` option means something like "I don't really care, just apply the default color for this platform", while two other options (`light-content` and `dark-content`) allow to accurately specify the required result.
Closes https://github.com/facebook/react-native/pull/10185

Differential Revision: D3952346

fbshipit-source-id: 999a67614abff52321fbeb06298ebf1946c3f1d1
This commit is contained in:
Alexander Pantyuhov 2016-09-30 12:49:05 -07:00 committed by Facebook Github Bot
parent 5b52dab781
commit c4ac8b329c
3 changed files with 41 additions and 8 deletions

View File

@ -24,13 +24,17 @@ const StatusBarManager = require('NativeModules').StatusBarManager;
*/
export type StatusBarStyle = $Enum<{
/**
* Default status bar style
* Default status bar style (dark for iOS, light for Android)
*/
'default': string,
/**
* Dark background style
* Dark background, white texts and icons
*/
'light-content': string,
/**
* Light background, dark texts and icons
*/
'dark-content': string,
}>;
/**
@ -134,7 +138,7 @@ class StatusBar extends React.Component {
animated?: boolean,
backgroundColor?: $FlowFixMe,
translucent?: boolean,
barStyle?: 'default' | 'light-content',
barStyle?: 'default' | 'light-content' | 'dark-content',
networkActivityIndicatorVisible?: boolean,
showHideTransition?: 'fade' | 'slide',
};
@ -191,13 +195,13 @@ class StatusBar extends React.Component {
* @param animated Animate the style change.
*/
static setBarStyle(style: StatusBarStyle, animated?: boolean) {
if (Platform.OS !== 'ios') {
console.warn('`setBarStyle` is only available on iOS');
return;
}
animated = animated || false;
StatusBar._defaultProps.barStyle.value = style;
StatusBarManager.setStyle(style, animated);
if (Platform.OS === 'ios') {
StatusBarManager.setStyle(style, animated);
} else if (Platform.OS === 'android') {
StatusBarManager.setStyle(style);
}
}
/**
@ -272,6 +276,7 @@ class StatusBar extends React.Component {
barStyle: React.PropTypes.oneOf([
'default',
'light-content',
'dark-content',
]),
/**
* If the network activity indicator should be visible.
@ -360,6 +365,9 @@ class StatusBar extends React.Component {
);
}
} else if (Platform.OS === 'android') {
if (!oldProps || oldProps.barStyle.value !== mergedProps.barStyle.value) {
StatusBarManager.setStyle(mergedProps.barStyle.value);
}
if (!oldProps || oldProps.backgroundColor.value !== mergedProps.backgroundColor.value) {
StatusBarManager.setColor(
processColor(mergedProps.backgroundColor.value),

View File

@ -18,6 +18,7 @@
RCT_ENUM_CONVERTER(UIStatusBarStyle, (@{
@"default": @(UIStatusBarStyleDefault),
@"light-content": @(UIStatusBarStyleLightContent),
@"dark-content": @(UIStatusBarStyleDefault),
}), UIStatusBarStyleDefault, integerValue);
RCT_ENUM_CONVERTER(UIStatusBarAnimation, (@{

View File

@ -170,4 +170,28 @@ public class StatusBarModule extends ReactContextBaseJavaModule {
}
});
}
@ReactMethod
public void setStyle(final String style, final Promise res) {
final Activity activity = getCurrentActivity();
if (activity == null) {
res.reject(ERROR_NO_ACTIVITY, ERROR_NO_ACTIVITY_MESSAGE);
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
UiThreadUtil.runOnUiThread(
new Runnable() {
@TargetApi(Build.VERSION_CODES.M)
@Override
public void run() {
View decorView = activity.getWindow().getDecorView();
decorView.setSystemUiVisibility(
style.equals("dark-content") ? View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : 0);
res.resolve(null);
}
}
);
}
}
}