Skip to content

Commit 039924e

Browse files
janicduplessisFacebook Github Bot 6
authored and
Facebook Github Bot 6
committed
Add statusBarBackgroundColor to DrawerLayoutAndroid to allow it to open over the status bar
Summary:The navigation drawer of most apps on android opens over the status bar, this adds an option to do so. It implements a similar API to the native DrawerLayout by adding a statusBarBackgroundColor to DrawerLayoutAndroid. Without statusBarBackgroundColor: ![image](https://cloud.githubusercontent.com/assets/2677334/13414490/50ebcdf4-df21-11e5-974f-c6a1343c2a4e.png) With statusBarBackgroundColor: ![image](https://cloud.githubusercontent.com/assets/2677334/13414459/1fdc4086-df21-11e5-9658-bd47bfdb925f.png) This PR depends on the changes in facebook#6195 to add the `StatusBar.HEIGHT` constant I just want to put it out there now to see if this looks good. To test without the other PR just change `StatusBar.HEIGHT` for `25`. It is implemented by making the native status bar translucent and making its background color transparent so we can draw a view of the same height as the status bar under it as a child of the DrawerLayoutAndroid. Then we can draw a semi-transparent gray View inside the drawer view to make it Closes facebook#6218 Differential Revision: D3017444 Pulled By: bestander fb-gh-sync-id: ca48a47a20a2feecae360a76f3e2c9bbe6a37700 fbshipit-source-id: ca48a47a20a2feecae360a76f3e2c9bbe6a37700
1 parent 5bbf88b commit 039924e

File tree

2 files changed

+79
-22
lines changed

2 files changed

+79
-22
lines changed

Diff for: Examples/UIExplorer/UIExplorerApp.android.js

+17-16
Original file line numberDiff line numberDiff line change
@@ -71,23 +71,26 @@ class UIExplorerApp extends React.Component {
7171
this._overrideBackPressForDrawerLayout = false;
7272
}}
7373
ref={(drawer) => { this.drawer = drawer; }}
74-
renderNavigationView={this._renderDrawerContent.bind(this, onNavigate)}>
74+
renderNavigationView={this._renderDrawerContent.bind(this, onNavigate)}
75+
statusBarBackgroundColor="#589c90">
7576
{this._renderNavigation(navigationState, onNavigate)}
7677
</DrawerLayoutAndroid>
7778
);
7879
}
7980

8081
_renderDrawerContent(onNavigate) {
8182
return (
82-
<UIExplorerExampleList
83-
list={UIExplorerList}
84-
displayTitleRow={true}
85-
disableSearch={true}
86-
onNavigate={(action) => {
87-
this.drawer && this.drawer.closeDrawer();
88-
onNavigate(action);
89-
}}
90-
/>
83+
<View style={styles.drawerContentWrapper}>
84+
<UIExplorerExampleList
85+
list={UIExplorerList}
86+
displayTitleRow={true}
87+
disableSearch={true}
88+
onNavigate={(action) => {
89+
this.drawer && this.drawer.closeDrawer();
90+
onNavigate(action);
91+
}}
92+
/>
93+
</View>
9194
);
9295
}
9396

@@ -113,9 +116,6 @@ class UIExplorerApp extends React.Component {
113116
const ExampleComponent = UIExplorerExampleList.makeRenderable(ExampleModule);
114117
return (
115118
<View style={styles.container}>
116-
<StatusBar
117-
backgroundColor="#589c90"
118-
/>
119119
<ToolbarAndroid
120120
logo={require('image!launcher_icon')}
121121
navIcon={require('image!ic_menu_black_24dp')}
@@ -131,9 +131,6 @@ class UIExplorerApp extends React.Component {
131131
}
132132
return (
133133
<View style={styles.container}>
134-
<StatusBar
135-
backgroundColor="#589c90"
136-
/>
137134
<ToolbarAndroid
138135
logo={require('image!launcher_icon')}
139136
navIcon={require('image!ic_menu_black_24dp')}
@@ -181,6 +178,10 @@ const styles = StyleSheet.create({
181178
backgroundColor: '#E9EAED',
182179
height: 56,
183180
},
181+
drawerContentWrapper: {
182+
paddingTop: StatusBar.currentHeight,
183+
backgroundColor: 'white',
184+
},
184185
});
185186

186187
AppRegistry.registerComponent('UIExplorerApp', () => UIExplorerApp);

Diff for: Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.android.js

+62-6
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@
1010
*/
1111
'use strict';
1212

13+
var ColorPropType = require('ColorPropType');
1314
var NativeMethodsMixin = require('NativeMethodsMixin');
15+
var Platform = require('Platform');
1416
var React = require('React');
1517
var ReactPropTypes = require('ReactPropTypes');
18+
var StatusBar = require('StatusBar');
1619
var StyleSheet = require('StyleSheet');
1720
var UIManager = require('UIManager');
1821
var View = require('View');
@@ -25,12 +28,6 @@ var requireNativeComponent = require('requireNativeComponent');
2528
var RK_DRAWER_REF = 'drawerlayout';
2629
var INNERVIEW_REF = 'innerView';
2730

28-
var DrawerLayoutValidAttributes = {
29-
drawerWidth: true,
30-
drawerPosition: true,
31-
drawerLockMode: true
32-
};
33-
3431
var DRAWER_STATES = [
3532
'Idle',
3633
'Dragging',
@@ -132,21 +129,52 @@ var DrawerLayoutAndroid = React.createClass({
132129
* The navigation view that will be rendered to the side of the screen and can be pulled in.
133130
*/
134131
renderNavigationView: ReactPropTypes.func.isRequired,
132+
133+
/**
134+
* Make the drawer take the entire screen and draw the background of the
135+
* status bar to allow it to open over the status bar. It will only have an
136+
* effect on API 21+.
137+
*/
138+
statusBarBackgroundColor: ColorPropType,
135139
},
136140

137141
mixins: [NativeMethodsMixin],
138142

143+
getInitialState: function() {
144+
return {statusBarBackgroundColor: undefined};
145+
},
146+
139147
getInnerViewNode: function() {
140148
return this.refs[INNERVIEW_REF].getInnerViewNode();
141149
},
142150

151+
componentDidMount: function() {
152+
this._updateStatusBarBackground();
153+
},
154+
155+
componentDidReceiveProps: function() {
156+
this._updateStatusBarBackground();
157+
},
158+
143159
render: function() {
160+
var drawStatusBar = Platform.Version >= 21 && this.props.statusBarBackgroundColor;
144161
var drawerViewWrapper =
145162
<View style={[styles.drawerSubview, {width: this.props.drawerWidth}]} collapsable={false}>
146163
{this.props.renderNavigationView()}
164+
{drawStatusBar && <View style={styles.drawerStatusBar} />}
147165
</View>;
148166
var childrenWrapper =
149167
<View ref={INNERVIEW_REF} style={styles.mainSubview} collapsable={false}>
168+
{drawStatusBar &&
169+
<StatusBar
170+
translucent
171+
backgroundColor={this.state.statusBarBackgroundColor}
172+
/>}
173+
{drawStatusBar &&
174+
<View style={[
175+
styles.statusBar,
176+
{backgroundColor: this.props.statusBarBackgroundColor}
177+
]} />}
150178
{this.props.children}
151179
</View>;
152180
return (
@@ -213,6 +241,23 @@ var DrawerLayoutAndroid = React.createClass({
213241
_getDrawerLayoutHandle: function() {
214242
return React.findNodeHandle(this.refs[RK_DRAWER_REF]);
215243
},
244+
245+
// Update the StatusBar component background color one frame after creating the
246+
// status bar background View to avoid a white flicker that happens because
247+
// the StatusBar background becomes transparent before the status bar View
248+
// from this component has rendered.
249+
_updateStatusBarBackground: function() {
250+
if (Platform.Version >= 21 && this.props.statusBarBackgroundColor) {
251+
// Check if the value is not already transparent to avoid an extra render.
252+
if (this.state.statusBarBackgroundColor !== 'transparent') {
253+
requestAnimationFrame(() => {
254+
this.setState({statusBarBackgroundColor: 'transparent'});
255+
});
256+
}
257+
} else {
258+
this.setState({statusBarBackgroundColor: undefined});
259+
}
260+
},
216261
});
217262

218263
var styles = StyleSheet.create({
@@ -233,6 +278,17 @@ var styles = StyleSheet.create({
233278
bottom: 0,
234279
backgroundColor: 'white',
235280
},
281+
statusBar: {
282+
height: StatusBar.currentHeight,
283+
},
284+
drawerStatusBar: {
285+
position: 'absolute',
286+
top: 0,
287+
left: 0,
288+
right: 0,
289+
height: StatusBar.currentHeight,
290+
backgroundColor: 'rgba(0, 0, 0, 0.251)',
291+
},
236292
});
237293

238294
// The View that contains both the actual drawer and the main view

0 commit comments

Comments
 (0)