fix: set screen background in drawer from theme

This commit is contained in:
Satyajit Sahoo
2019-12-17 00:01:47 +01:00
parent 9843b92e05
commit 0635365483
4 changed files with 94 additions and 134 deletions

View File

@@ -19,7 +19,7 @@ import {
type Props = DefaultNavigatorOptions<DrawerNavigationOptions> &
DrawerRouterOptions &
Partial<DrawerNavigationConfig>;
DrawerNavigationConfig;
function DrawerNavigator({
initialRouteName,

View File

@@ -20,14 +20,14 @@ export type DrawerNavigationConfig<T = DrawerContentOptions> = {
/**
* Position of the drawer on the screen. Defaults to `left`.
*/
drawerPosition: 'left' | 'right';
drawerPosition?: 'left' | 'right';
/**
* Type of the drawer. It determines how the drawer looks and animates.
* - `front`: Traditional drawer which covers the screen with a overlay behind it.
* - `back`: The drawer is revealed behind the screen on swipe.
* - `slide`: Both the screen and the drawer slide on swipe to reveal the drawer.
*/
drawerType: 'front' | 'back' | 'slide';
drawerType?: 'front' | 'back' | 'slide';
/**
* How far from the edge of the screen the swipe gesture should activate.
*/
@@ -35,12 +35,12 @@ export type DrawerNavigationConfig<T = DrawerContentOptions> = {
/**
* Whether the statusbar should be hidden when the drawer is pulled or opens,
*/
hideStatusBar: boolean;
hideStatusBar?: boolean;
/**
* Whether the keyboard should be dismissed when the swipe gesture begins.
* Defaults to `'on-drag'`. Set to `'none'` to disable keyboard handling.
*/
keyboardDismissMode: 'on-drag' | 'none';
keyboardDismissMode?: 'on-drag' | 'none';
/**
* Minimum swipe distance threshold that should activate opening the drawer.
*/
@@ -53,7 +53,7 @@ export type DrawerNavigationConfig<T = DrawerContentOptions> = {
/**
* Animation of the statusbar when hiding it. use in combination with `hideStatusBar`.
*/
statusBarAnimation: 'slide' | 'none' | 'fade';
statusBarAnimation?: 'slide' | 'none' | 'fade';
/**
* Props to pass to the underlying pan gesture handler.
*/
@@ -62,7 +62,7 @@ export type DrawerNavigationConfig<T = DrawerContentOptions> = {
* Whether the screens should render the first time they are accessed. Defaults to `true`.
* Set it to `false` if you want to render all screens on initial render.
*/
lazy: boolean;
lazy?: boolean;
/**
* Whether a screen should be unmounted when navigating away from it.
* Defaults to `false`.
@@ -72,7 +72,7 @@ export type DrawerNavigationConfig<T = DrawerContentOptions> = {
* Function that returns React element to render as the content of the drawer, for example, navigation items.
* Defaults to `DrawerContent`.
*/
drawerContent: (props: DrawerContentComponentProps<T>) => React.ReactNode;
drawerContent?: (props: DrawerContentComponentProps<T>) => React.ReactNode;
/**
* Options for the content component which will be passed as props.
*/

View File

@@ -1,7 +1,6 @@
import * as React from 'react';
import { ScrollView, StyleSheet, ScrollViewProps } from 'react-native';
import { useSafeArea } from 'react-native-safe-area-context';
import { useTheme } from '@react-navigation/native';
type Props = ScrollViewProps & {
drawerPosition: 'left' | 'right';
@@ -16,7 +15,6 @@ export default function DrawerContentScrollView({
...rest
}: Props) {
const insets = useSafeArea();
const { colors } = useTheme();
return (
<ScrollView
@@ -29,7 +27,7 @@ export default function DrawerContentScrollView({
},
contentContainerStyle,
]}
style={[styles.container, { backgroundColor: colors.card }, style]}
style={[styles.container, style]}
>
{children}
</ScrollView>

View File

@@ -13,6 +13,7 @@ import {
DrawerNavigationState,
DrawerActions,
} from '@react-navigation/routers';
import { useTheme } from '@react-navigation/native';
import DrawerGestureContext from '../utils/DrawerGestureContext';
import SafeAreaProviderCompat from './SafeAreaProviderCompat';
@@ -26,16 +27,10 @@ import {
DrawerContentComponentProps,
} from '../types';
type Props = Omit<DrawerNavigationConfig, 'overlayColor'> & {
type Props = DrawerNavigationConfig & {
state: DrawerNavigationState;
navigation: DrawerNavigationHelpers;
descriptors: DrawerDescriptorMap;
overlayColor: string;
};
type State = {
loaded: number[];
drawerWidth: number;
};
const getDefaultDrawerWidth = ({
@@ -62,49 +57,52 @@ const getDefaultDrawerWidth = ({
/**
* Component that renders the drawer.
*/
export default class DrawerView extends React.PureComponent<Props, State> {
static defaultProps = {
lazy: true,
drawerContent: (props: DrawerContentComponentProps) => (
<DrawerContent {...props} />
),
drawerPosition: I18nManager.isRTL ? 'right' : 'left',
keyboardDismissMode: 'on-drag',
overlayColor: 'rgba(0, 0, 0, 0.5)',
drawerType: 'front',
hideStatusBar: false,
statusBarAnimation: 'slide',
};
export default function DrawerView({
state,
navigation,
descriptors,
lazy = true,
drawerContent = (props: DrawerContentComponentProps) => (
<DrawerContent {...props} />
),
drawerPosition = I18nManager.isRTL ? 'right' : 'left',
keyboardDismissMode = 'on-drag',
overlayColor = 'rgba(0, 0, 0, 0.5)',
drawerType = 'front',
hideStatusBar = false,
statusBarAnimation = 'slide',
drawerContentOptions,
drawerStyle,
edgeWidth,
gestureHandlerProps,
minSwipeDistance,
sceneContainerStyle,
unmountInactiveScreens,
}: Props) {
const [loaded, setLoaded] = React.useState([state.index]);
const [drawerWidth, setDrawerWidth] = React.useState(() =>
getDefaultDrawerWidth(Dimensions.get('window'))
);
static getDerivedStateFromProps(nextProps: Props, prevState: State) {
const { index } = nextProps.state;
const drawerGestureRef = React.useRef<PanGestureHandler>(null);
return {
// Set the current tab to be loaded if it was not loaded before
loaded: prevState.loaded.includes(index)
? prevState.loaded
: [...prevState.loaded, index],
const { colors } = useTheme();
React.useEffect(() => {
const updateWidth = ({ window }: { window: ScaledSize }) => {
setDrawerWidth(getDefaultDrawerWidth(window));
};
Dimensions.addEventListener('change', updateWidth);
return () => Dimensions.removeEventListener('change', updateWidth);
}, []);
if (!loaded.includes(state.index)) {
setLoaded([...loaded, state.index]);
}
state: State = {
loaded: [this.props.state.index],
drawerWidth: getDefaultDrawerWidth(Dimensions.get('window')),
};
componentDidMount() {
Dimensions.addEventListener('change', this.updateWidth);
}
componentWillUnmount() {
Dimensions.removeEventListener('change', this.updateWidth);
}
private drawerGestureRef = React.createRef<PanGestureHandler>();
private handleDrawerOpen = () => {
const { state, navigation } = this.props;
const handleDrawerOpen = () => {
navigation.dispatch({
...DrawerActions.openDrawer(),
target: state.key,
@@ -113,9 +111,7 @@ export default class DrawerView extends React.PureComponent<Props, State> {
navigation.emit({ type: 'drawerOpen' });
};
private handleDrawerClose = () => {
const { state, navigation } = this.props;
const handleDrawerClose = () => {
navigation.dispatch({
...DrawerActions.closeDrawer(),
target: state.key,
@@ -124,24 +120,7 @@ export default class DrawerView extends React.PureComponent<Props, State> {
navigation.emit({ type: 'drawerClose' });
};
private updateWidth = ({ window }: { window: ScaledSize }) => {
const drawerWidth = getDefaultDrawerWidth(window);
if (this.state.drawerWidth !== drawerWidth) {
this.setState({ drawerWidth });
}
};
private renderNavigationView = ({ progress }: any) => {
const {
state,
navigation,
descriptors,
drawerPosition,
drawerContent,
drawerContentOptions,
} = this.props;
const renderNavigationView = ({ progress }: any) => {
return drawerContent({
...drawerContentOptions,
progress: progress,
@@ -152,11 +131,7 @@ export default class DrawerView extends React.PureComponent<Props, State> {
});
};
private renderContent = () => {
let { lazy, state, descriptors, unmountInactiveScreens } = this.props;
const { loaded } = this.state;
const renderContent = () => {
return (
<ScreenContainer style={styles.content}>
{state.routes.map((route, index) => {
@@ -164,7 +139,7 @@ export default class DrawerView extends React.PureComponent<Props, State> {
return null;
}
if (lazy && !loaded.includes(index)) {
if (lazy && !loaded.includes(index) && index !== state.index) {
// Don't render a screen if we've never navigated to it
return null;
}
@@ -186,58 +161,45 @@ export default class DrawerView extends React.PureComponent<Props, State> {
);
};
private setDrawerGestureRef = (ref: PanGestureHandler | null) => {
// @ts-ignore
this.drawerGestureRef.current = ref;
};
const activeKey = state.routes[state.index].key;
const { gestureEnabled } = descriptors[activeKey].options;
render() {
const {
state,
descriptors,
drawerType,
drawerPosition,
overlayColor,
sceneContainerStyle,
drawerStyle,
edgeWidth,
minSwipeDistance,
hideStatusBar,
statusBarAnimation,
gestureHandlerProps,
} = this.props;
const { drawerWidth } = this.state;
const activeKey = state.routes[state.index].key;
const { gestureEnabled } = descriptors[activeKey].options;
return (
<SafeAreaProviderCompat>
<DrawerGestureContext.Provider value={this.drawerGestureRef}>
<Drawer
open={state.isDrawerOpen}
gestureEnabled={gestureEnabled !== false}
onOpen={this.handleDrawerOpen}
onClose={this.handleDrawerClose}
onGestureRef={this.setDrawerGestureRef}
gestureHandlerProps={gestureHandlerProps}
drawerType={drawerType}
drawerPosition={drawerPosition}
sceneContainerStyle={sceneContainerStyle}
drawerStyle={[{ width: drawerWidth }, drawerStyle]}
overlayStyle={{ backgroundColor: overlayColor }}
swipeEdgeWidth={edgeWidth}
swipeDistanceThreshold={minSwipeDistance}
hideStatusBar={hideStatusBar}
statusBarAnimation={statusBarAnimation}
renderDrawerContent={this.renderNavigationView}
renderSceneContent={this.renderContent}
/>
</DrawerGestureContext.Provider>
</SafeAreaProviderCompat>
);
}
return (
<SafeAreaProviderCompat>
<DrawerGestureContext.Provider value={drawerGestureRef}>
<Drawer
open={state.isDrawerOpen}
gestureEnabled={gestureEnabled !== false}
onOpen={handleDrawerOpen}
onClose={handleDrawerClose}
onGestureRef={ref => {
// @ts-ignore
drawerGestureRef.current = ref;
}}
gestureHandlerProps={gestureHandlerProps}
drawerType={drawerType}
drawerPosition={drawerPosition}
sceneContainerStyle={[
{ backgroundColor: colors.background },
sceneContainerStyle,
]}
drawerStyle={[
{ width: drawerWidth, backgroundColor: colors.card },
drawerStyle,
]}
overlayStyle={{ backgroundColor: overlayColor }}
swipeEdgeWidth={edgeWidth}
swipeDistanceThreshold={minSwipeDistance}
hideStatusBar={hideStatusBar}
statusBarAnimation={statusBarAnimation}
renderDrawerContent={renderNavigationView}
renderSceneContent={renderContent}
keyboardDismissMode={keyboardDismissMode}
drawerPostion={drawerPosition}
/>
</DrawerGestureContext.Provider>
</SafeAreaProviderCompat>
);
}
const styles = StyleSheet.create({