Skip to content

Commit b979128

Browse files
janicduplessisfacebook-github-bot-7
authored andcommitted
Cross platform status bar API
Summary: I started working on improving the `StatusBar` API and make it work on Android. I added support for `setColor`, `setTranslucent` (the status bar is still visible but the app can draw under) and `setHidden` on Android. Looking for feedback on how to improve the API before I put more time on this :). Right now I went for a cross platform API and functions that don't exist on a platform are just a no-op but I'm not sure it is the best choice since at the moment what is supported is very different between both platforms. I was wondering what you guys think and if it would be better off as 2 different modules. It is also possible to port some of the features I added for Android to iOS even if there is no 'standard' way to do it. Like `setColor` could be implemented by drawing a colored view under the status bar and translucent by adding/removing some padding. Closes facebook/react-native#5360 Reviewed By: svcscm Differential Revision: D2840417 Pulled By: nicklockwood fb-gh-sync-id: 5c8d988bccf8035341f0efe27e54dd8402c18d24
1 parent 0c91931 commit b979128

14 files changed

Lines changed: 588 additions & 17 deletions

File tree

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
/**
2+
* The examples provided by Facebook are for non-commercial testing and
3+
* evaluation purposes only.
4+
*
5+
* Facebook reserves all rights not expressly granted.
6+
*
7+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
8+
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9+
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
10+
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
11+
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
12+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13+
*
14+
* @flow
15+
*/
16+
'use strict';
17+
18+
const React = require('react-native');
19+
const {
20+
StyleSheet,
21+
View,
22+
Text,
23+
TouchableHighlight,
24+
StatusBar,
25+
} = React;
26+
27+
type BarStyle = 'default' | 'light-content';
28+
type ShowHideTransition = 'fade' | 'slide';
29+
30+
type State = {
31+
animated: boolean,
32+
backgroundColor: string,
33+
hidden?: boolean,
34+
showHideTransition: ShowHideTransition,
35+
translucent?: boolean,
36+
barStyle?: BarStyle,
37+
networkActivityIndicatorVisible?: boolean
38+
};
39+
40+
exports.framework = 'React';
41+
exports.title = '<StatusBar>';
42+
exports.description = 'Component for controlling the status bar';
43+
44+
const colors = [
45+
'#ff0000',
46+
'#00ff00',
47+
'#0000ff',
48+
];
49+
50+
const barStyles = [
51+
'default',
52+
'light-content',
53+
];
54+
55+
const showHideTransitions = [
56+
'fade',
57+
'slide',
58+
];
59+
60+
const StatusBarExample = React.createClass({
61+
getInitialState(): State {
62+
return {
63+
animated: true,
64+
backgroundColor: this._getValue(colors, 0),
65+
showHideTransition: this._getValue(showHideTransitions, 0),
66+
};
67+
},
68+
69+
_colorIndex: 0,
70+
_barStyleIndex: 0,
71+
_showHideTransitionIndex: 0,
72+
73+
_getValue(values: Array<any>, index: number): any {
74+
return values[index % values.length];
75+
},
76+
77+
render() {
78+
return (
79+
<View>
80+
<StatusBar
81+
backgroundColor={this.state.backgroundColor}
82+
translucent={this.state.translucent}
83+
hidden={this.state.hidden}
84+
showHideTransition={this.state.showHideTransition}
85+
animated={this.state.animated}
86+
barStyle={this.state.barStyle}
87+
networkActivityIndicatorVisible={this.state.networkActivityIndicatorVisible}
88+
/>
89+
<View>
90+
<TouchableHighlight
91+
style={styles.wrapper}
92+
onPress={() => this.setState({animated: !this.state.animated})}>
93+
<View style={styles.button}>
94+
<Text>animated: {this.state.animated ? 'true' : 'false'}</Text>
95+
</View>
96+
</TouchableHighlight>
97+
</View>
98+
<View>
99+
<TouchableHighlight
100+
style={styles.wrapper}
101+
onPress={() => this.setState({hidden: !this.state.hidden})}>
102+
<View style={styles.button}>
103+
<Text>hidden: {this.state.hidden ? 'true' : 'false'}</Text>
104+
</View>
105+
</TouchableHighlight>
106+
</View>
107+
<Text style={styles.title}>iOS</Text>
108+
<View>
109+
<TouchableHighlight
110+
style={styles.wrapper}
111+
onPress={() => {
112+
this._barStyleIndex++;
113+
this.setState({barStyle: this._getValue(barStyles, this._barStyleIndex)});
114+
}}>
115+
<View style={styles.button}>
116+
<Text>style: '{this._getValue(barStyles, this._barStyleIndex)}'</Text>
117+
</View>
118+
</TouchableHighlight>
119+
</View>
120+
<View>
121+
<TouchableHighlight
122+
style={styles.wrapper}
123+
onPress={() => this.setState({
124+
networkActivityIndicatorVisible: !this.state.networkActivityIndicatorVisible,
125+
})}>
126+
<View style={styles.button}>
127+
<Text>
128+
networkActivityIndicatorVisible:
129+
{this.state.networkActivityIndicatorVisible ? 'true' : 'false'}
130+
</Text>
131+
</View>
132+
</TouchableHighlight>
133+
</View>
134+
<View>
135+
<TouchableHighlight
136+
style={styles.wrapper}
137+
onPress={() => {
138+
this._showHideTransitionIndex++;
139+
this.setState({
140+
showHideTransition:
141+
this._getValue(showHideTransitions, this._showHideTransitionIndex),
142+
});
143+
}}>
144+
<View style={styles.button}>
145+
<Text>
146+
showHideTransition:
147+
'{this._getValue(showHideTransitions, this._showHideTransitionIndex)}'
148+
</Text>
149+
</View>
150+
</TouchableHighlight>
151+
</View>
152+
<Text style={styles.title}>Android</Text>
153+
<View>
154+
<TouchableHighlight
155+
style={styles.wrapper}
156+
onPress={() => {
157+
this._colorIndex++;
158+
this.setState({backgroundColor: this._getValue(colors, this._colorIndex)});
159+
}}>
160+
<View style={styles.button}>
161+
<Text>backgroundColor: '{this._getValue(colors, this._colorIndex)}'</Text>
162+
</View>
163+
</TouchableHighlight>
164+
</View>
165+
<View>
166+
<TouchableHighlight
167+
style={styles.wrapper}
168+
onPress={() => {
169+
this.setState({
170+
translucent: !this.state.translucent,
171+
backgroundColor: !this.state.translucent ? 'rgba(0, 0, 0, 0.4)' : 'black',
172+
});
173+
}}>
174+
<View style={styles.button}>
175+
<Text>translucent: {this.state.translucent ? 'true' : 'false'}</Text>
176+
</View>
177+
</TouchableHighlight>
178+
</View>
179+
</View>
180+
);
181+
},
182+
});
183+
184+
exports.examples = [{
185+
title: 'Status Bar',
186+
render() {
187+
return <StatusBarExample />;
188+
},
189+
}];
190+
191+
var styles = StyleSheet.create({
192+
wrapper: {
193+
borderRadius: 5,
194+
marginBottom: 5,
195+
},
196+
button: {
197+
borderRadius: 5,
198+
backgroundColor: '#eeeeee',
199+
padding: 10,
200+
},
201+
title: {
202+
marginTop: 16,
203+
marginBottom: 8,
204+
fontWeight: 'bold',
205+
}
206+
});

Examples/UIExplorer/UIExplorerApp.android.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ var {
2525
StyleSheet,
2626
ToolbarAndroid,
2727
View,
28+
StatusBar,
2829
} = React;
2930
var UIExplorerList = require('./UIExplorerList.android');
3031

@@ -98,6 +99,9 @@ var UIExplorerApp = React.createClass({
9899
var Component = this.state.example.component;
99100
return (
100101
<View style={styles.container}>
102+
<StatusBar
103+
backgroundColor="#589c90"
104+
/>
101105
<ToolbarAndroid
102106
logo={require('image!launcher_icon')}
103107
navIcon={require('image!ic_menu_black_24dp')}

Examples/UIExplorer/UIExplorerApp.ios.js

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ var {
2424
StyleSheet,
2525
Text,
2626
TouchableHighlight,
27-
View
27+
View,
28+
StatusBar,
2829
} = React;
2930

3031
var UIExplorerApp = React.createClass({
@@ -48,20 +49,23 @@ var UIExplorerApp = React.createClass({
4849
}
4950

5051
return (
51-
<NavigatorIOS
52-
style={styles.container}
53-
initialRoute={{
54-
title: 'UIExplorer',
55-
component: UIExplorerList,
56-
passProps: {
57-
onExternalExampleRequested: (example) => {
58-
this.setState({ openExternalExample: example, });
59-
},
60-
}
61-
}}
62-
itemWrapperStyle={styles.itemWrapper}
63-
tintColor="#008888"
64-
/>
52+
<View style={{flex: 1}}>
53+
<StatusBar barStyle="default" />
54+
<NavigatorIOS
55+
style={styles.container}
56+
initialRoute={{
57+
title: 'UIExplorer',
58+
component: UIExplorerList,
59+
passProps: {
60+
onExternalExampleRequested: (example) => {
61+
this.setState({ openExternalExample: example, });
62+
},
63+
}
64+
}}
65+
itemWrapperStyle={styles.itemWrapper}
66+
tintColor="#008888"
67+
/>
68+
</View>
6569
);
6670
}
6771
});

Examples/UIExplorer/UIExplorerList.android.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ var COMPONENTS = [
3030
require('./PullToRefreshViewAndroidExample.android'),
3131
require('./RefreshControlExample'),
3232
require('./ScrollViewSimpleExample'),
33+
require('./StatusBarExample'),
3334
require('./SwitchExample'),
3435
require('./TextExample.android'),
3536
require('./TextInputExample.android'),

Examples/UIExplorer/UIExplorerList.ios.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ var COMPONENTS = [
4646
require('./ScrollViewExample'),
4747
require('./SegmentedControlIOSExample'),
4848
require('./SliderIOSExample'),
49+
require('./StatusBarExample'),
4950
require('./SwitchExample'),
5051
require('./TabBarIOSExample'),
5152
require('./TextExample.ios'),

0 commit comments

Comments
 (0)