mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-03-06 17:34:59 +08:00
Fix default width of drawer (#2978)
* Fix default width of drawer Current implementation is simplified / broken. - The drawerWidth doesn't work for tablets, the drawer becomes massively large - Header size changes (and thus drawer width changes) in landscape mode on iOS are not accounted for - An incorrect 64px header size is used for iOS (this includes the status bar height that doesn't belong in the calculation) Implement a default drawerWidth as a function that follows the Material Design spec closer: - Screen width - header height - Use the correct iOS app bar height in portrait and landscape mode - Drawer max height of 280 on mobile and 320 on tablet * Update snapshot for drawer width change
This commit is contained in:
committed by
Dave Pack
parent
346264e132
commit
e25bdd2ed2
@@ -87,7 +87,7 @@ The route configs object is a mapping from route name to a route config, which t
|
||||
|
||||
|
||||
### DrawerNavigatorConfig
|
||||
- `drawerWidth` - Width of the drawer.
|
||||
- `drawerWidth` - Width of the drawer or a function returning it.
|
||||
- `drawerPosition` - Options are `left` or `right`. Default is `left` position.
|
||||
- `contentComponent` - Component used to render the content of the drawer, for example, navigation items. Receives the `navigation` prop for the drawer. Defaults to `DrawerItems`. For more information, see below.
|
||||
- `contentOptions` - Configure the drawer content, see below.
|
||||
|
||||
@@ -24,8 +24,6 @@ export type DrawerNavigatorConfig = {
|
||||
} & NavigationTabRouterConfig &
|
||||
DrawerViewConfig;
|
||||
|
||||
const { height, width } = Dimensions.get('window');
|
||||
|
||||
const defaultContentComponent = (props: *) => (
|
||||
<ScrollView alwaysBounceVertical={false}>
|
||||
<SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
|
||||
@@ -35,11 +33,21 @@ const defaultContentComponent = (props: *) => (
|
||||
);
|
||||
|
||||
const DefaultDrawerConfig = {
|
||||
/*
|
||||
* Default drawer width is screen width - header width
|
||||
* https://material.io/guidelines/patterns/navigation-drawer.html
|
||||
*/
|
||||
drawerWidth: Math.min(height, width) - (Platform.OS === 'android' ? 56 : 64),
|
||||
drawerWidth: () => {
|
||||
/*
|
||||
* Default drawer width is screen width - header height
|
||||
* with a max width of 280 on mobile and 320 on tablet
|
||||
* https://material.io/guidelines/patterns/navigation-drawer.html
|
||||
*/
|
||||
const { height, width } = Dimensions.get('window');
|
||||
const smallerAxisSize = Math.min(height, width);
|
||||
const isLandscape = width > height;
|
||||
const isTablet = smallerAxisSize >= 600;
|
||||
const appBarHeight = Platform.OS === 'ios' ? (isLandscape ? 32 : 44) : 56;
|
||||
const maxWidth = isTablet ? 320 : 280;
|
||||
|
||||
return Math.min(smallerAxisSize - appBarHeight, maxWidth);
|
||||
},
|
||||
contentComponent: defaultContentComponent,
|
||||
drawerPosition: 'left',
|
||||
drawerBackgroundColor: 'white',
|
||||
|
||||
@@ -73,10 +73,10 @@ exports[`DrawerNavigator renders successfully 1`] = `
|
||||
"top": 0,
|
||||
"transform": Array [
|
||||
Object {
|
||||
"translateX": -686,
|
||||
"translateX": -320,
|
||||
},
|
||||
],
|
||||
"width": 686,
|
||||
"width": 320,
|
||||
"zIndex": 1001,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* @flow */
|
||||
|
||||
import * as React from 'react';
|
||||
import { Dimensions } from 'react-native';
|
||||
import DrawerLayout from 'react-native-drawer-layout-polyfill';
|
||||
|
||||
import addNavigationHelpers from '../../addNavigationHelpers';
|
||||
@@ -31,7 +32,7 @@ export type DrawerItem = {
|
||||
|
||||
export type DrawerViewConfig = {
|
||||
drawerLockMode?: 'unlocked' | 'locked-closed' | 'locked-open',
|
||||
drawerWidth?: number,
|
||||
drawerWidth?: number | (() => number),
|
||||
drawerPosition?: 'left' | 'right',
|
||||
contentComponent?: React.ComponentType<*>,
|
||||
contentOptions?: {},
|
||||
@@ -53,14 +54,32 @@ export type DrawerViewProps = DrawerViewPropsExceptRouter & {
|
||||
>,
|
||||
};
|
||||
|
||||
type DrawerViewState = {
|
||||
drawerWidth?: number,
|
||||
};
|
||||
|
||||
/**
|
||||
* Component that renders the drawer.
|
||||
*/
|
||||
export default class DrawerView<T: NavigationRoute> extends React.PureComponent<
|
||||
DrawerViewProps
|
||||
DrawerViewProps,
|
||||
DrawerViewState
|
||||
> {
|
||||
state: DrawerViewState = {
|
||||
drawerWidth:
|
||||
typeof this.props.drawerWidth === 'function'
|
||||
? this.props.drawerWidth()
|
||||
: this.props.drawerWidth,
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
this._updateScreenNavigation(this.props.navigation);
|
||||
|
||||
Dimensions.addEventListener('change', this._updateWidth);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
Dimensions.removeEventListener('change', this._updateWidth);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: DrawerViewProps) {
|
||||
@@ -120,6 +139,17 @@ export default class DrawerView<T: NavigationRoute> extends React.PureComponent<
|
||||
});
|
||||
};
|
||||
|
||||
_updateWidth = () => {
|
||||
const drawerWidth =
|
||||
typeof this.props.drawerWidth === 'function'
|
||||
? this.props.drawerWidth()
|
||||
: this.props.drawerWidth;
|
||||
|
||||
if (this.state.drawerWidth !== drawerWidth) {
|
||||
this.setState({ drawerWidth });
|
||||
}
|
||||
};
|
||||
|
||||
_getNavigationState = (navigation: NavigationScreenProp<NavigationState>) => {
|
||||
const navigationState = navigation.state.routes.find(
|
||||
(route: *) => route.routeName === 'DrawerClose'
|
||||
@@ -166,7 +196,7 @@ export default class DrawerView<T: NavigationRoute> extends React.PureComponent<
|
||||
(config && config.drawerLockMode)
|
||||
}
|
||||
drawerBackgroundColor={this.props.drawerBackgroundColor}
|
||||
drawerWidth={this.props.drawerWidth}
|
||||
drawerWidth={this.state.drawerWidth}
|
||||
onDrawerOpen={this._handleDrawerOpen}
|
||||
onDrawerClose={this._handleDrawerClose}
|
||||
useNativeAnimations={this.props.useNativeAnimations}
|
||||
|
||||
Reference in New Issue
Block a user