Jo Momma
Jo Momma

Reputation: 1307

How to prevent drawer swipe gesture from a navigator

I'm using React Navigation 5+. They have changed the way you configure Navigators and I'm trying to implement it in my program. I have a DrawerNavigator as a top-level navigator. The first screen is a StackNavigator with a few screens. I'm looking for a way to prevent the user from swiping the drawer open on every screen except for the first screen. Here is my Navigator file:

const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();

function CheckinStack() {
    return (
        <Stack.Navigator
            initialRouteName={"Loading"}
            headerMode={"none"}
        >
            <Stack.Screen 
                name={"Search Locations"} 
                component={SearchLocationsScreen} 
                options={{gestureEnabled: true}}
            />
            <Stack.Screen 
                name={"Check In Form"} 
                component={CheckInFormScreen} 
                options={{gestureEnabled: false}}
            />
            <Stack.Screen 
                name={"Checked In"} 
                component={CheckedInScreen} 
                options={{gestureEnabled: false}}
            />
            <Stack.Screen 
                name={"Business Details"} 
                component={BusinessDetailsScreen} 
                options={{gestureEnabled: false}}
            />
        </Stack.Navigator>
    );
}

function MainDrawer() {
    return (
        <Drawer.Navigator >
            <Drawer.Screen name={"Search Locations"} component={CheckinStack}/>
            <Drawer.Screen name={"About"} component={AboutScreen}/>
            <Drawer.Screen name={"Favorites"} component={FavoritesScreen}/>
            <Drawer.Screen name={"Profile"} component={ProfileScreen}/>
            <Drawer.Screen name={"Report Issues"} component={ReportIssuesScreen}/>
        </Drawer.Navigator>
    );
}

const NavContainer = (props) => {
    return (
        <NavigationContainer>
            <MainDrawer />
        </NavigationContainer>
    )
};

export default NavContainer

As you can see I have attempted to set gestureEnabled to false on every screen but one (which is my main screen). It has no effect. If I set gestureEnabled to false on the navigator itself, it prevents the drawer swipe gesture on all of the screens.

I have attempted code like this inside the screen:

CheckInFormScreen.navigationOptions = navData => {
    return {
        gestureEnabled: false
    }
};

I didn't really expect this to work but I was just throwing stuff out there. How can I allow the user to swipe open the Drawer on the SearchLocationsScreen of the NavigationStack but not on the rest of the NavigationStack's screens?

Upvotes: 0

Views: 2325

Answers (2)

Jo Momma
Jo Momma

Reputation: 1307

Ok, I understand that React-Native is a bit of a buggy process. I did however figure a solution to my problem.

To solve the problem I got a reference to the parent navigator using dangerouslyGetParent and then set the options on it.

Keep in mind, you use options when configuring a screen and you use screenOptions when you are configuring all the screens in the navigator. These props replace navigationOptions and defaultNavigationOptions from react-navigation 4+

Here is the full code:

const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();

function CheckinStack({props}) {
    return (
        <Stack.Navigator
            initialRouteName={"Loading"}
            headerMode={"none"}
        >
            <Stack.Screen
                name={"Loading"}
                component={LoadingScreen}
                options={props => {
                    let parent = props.navigation.dangerouslyGetParent();
                    parent.setOptions({
                        gestureEnabled: false
                    })
                }}
            />
            <Stack.Screen
                name={"Search Locations"}
                component={SearchLocationsScreen}
                options={props => {
                    let parent = props.navigation.dangerouslyGetParent();
                    parent.setOptions({
                        gestureEnabled: true
                    })
                }}
            />
            <Stack.Screen
                name={"Check In Form"}
                component={CheckInFormScreen}
                options={props => {
                    let parent = props.navigation.dangerouslyGetParent();
                    parent.setOptions({
                        gestureEnabled: false
                    })
                }}
            />
            <Stack.Screen
                name={"Checked In"}
                component={CheckedInScreen}
                options={props => {
                    let parent = props.navigation.dangerouslyGetParent();
                    parent.setOptions({
                        gestureEnabled: false
                    })
                }}
            />
            <Stack.Screen
                name={"Business Details"}
                component={BusinessDetailsScreen}
                options={props => {
                    let parent = props.navigation.dangerouslyGetParent();
                    parent.setOptions({
                        gestureEnabled: false
                    })
                }}
            />
        </Stack.Navigator>
    );
}

function MainDrawer() {
    return (
        <Drawer.Navigator >
            <Drawer.Screen name={"Search Locations Stack"} component={CheckinStack}/>
            <Drawer.Screen name={"About"} component={AboutScreen}/>
            <Drawer.Screen name={"Favorites"} component={FavoritesScreen}/>
            <Drawer.Screen name={"Profile"} component={ProfileScreen}/>
            <Drawer.Screen name={"Report Issues"} component={ReportIssuesScreen}/>
        </Drawer.Navigator>
    );
}

const NavContainer = (props) => {
    return (
        <NavigationContainer>
            <MainDrawer />
        </NavigationContainer>
    )
};

export default NavContainer

Upvotes: 6

Victor
Victor

Reputation: 4199

Update: If the below code doesnt work , Please refer Screen options resolution

Did you try using 'drawerLockMode'

FeedStack.navigationOptions = () => {
   return { drawerLockMode: 'locked-closed' }
}

I think you can add this prop in options

function CheckinStack() {
    return (
        <Stack.Navigator
            initialRouteName={"Loading"}
            headerMode={"none"}
        >
            <Stack.Screen 
                name={"Search Locations"} 
                component={SearchLocationsScreen} 
            />
            <Stack.Screen 
                name={"Check In Form"} 
                component={CheckInFormScreen}
                options={{drawerLockMode: 'locked-closed'}} 
            />
            <Stack.Screen 
                name={"Checked In"} 
                component={CheckedInScreen}
                options={{drawerLockMode: 'locked-closed'}}
            />
            <Stack.Screen 
                name={"Business Details"} 
                component={BusinessDetailsScreen} 
                options={{drawerLockMode: 'locked-closed'}}
            />
        </Stack.Navigator>
    );
}

Upvotes: 1

Related Questions