Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable swipe back action in stack navigation (react-navigation). #1063

Closed
tungbt-2-3-1994 opened this issue Apr 16, 2017 · 55 comments
Closed

Comments

@tungbt-2-3-1994
Copy link

tungbt-2-3-1994 commented Apr 16, 2017

I have 2 screens A and B in stack navigator. When i click button on screen A, it will navigate to screen B. On screen B, I want to disable the swipe back action. I just want that when i press left button in navigation, i will navigate back to screen A.
Thanks in advance!

@narendrashetty
Copy link

@tungbt-2-3-1994 Did you find the solution for it?

@tungbt-2-3-1994
Copy link
Author

@narendrashetty
In navigationOptions, you add
/*
cardStack: {
gesturesEnabled: false,
},
*/
It helps for me.

@anton6
Copy link

anton6 commented Jul 4, 2017

Example of route definition with gesturesEnabled: false

Example: {
    name: 'Example Screen',
    screen: ExampleView
    navigationOptions: {
        gesturesEnabled: false,
    },
},

For me, for some reason it does not work if I wrap gesturesEnabled: false with cardStack.

@bobzhen
Copy link

bobzhen commented Jul 28, 2017

@anton6 this is brilliant

@agersoncgps
Copy link

Any way to set this globally for all routes?

@jlc467
Copy link

jlc467 commented Sep 18, 2017

@agersoncgps StackNavigator takes navigationOptions representing the "Default navigation options to use for screens"

Example:

const RootStackNavigator = StackNavigator(
  {
    Login: {
      screen: LoginScreen
    },
    Main: {
      screen: MainDrawerNavigator
    }
  },
  {
    index: 0,
    initialRouteName: 'Login',
    headerMode: 'none',
    navigationOptions: {
      gesturesEnabled: false
    }
  }
);

@hedza06
Copy link

hedza06 commented Apr 6, 2018

@anton6 thanks man! You made my day!!! <3

@SirPhemmiey
Copy link

So as not to make your stuff messy, create a function and call it wherever you need it.

_goHome() {
let toHome = NavigationActions.reset({
index: 0,
actions: [NavigationActions.navigate({routeName: 'Home'})]
});
this.props.navigation.dispatch(toHome)
}

Then call it like so this._goHome()

@eflatz
Copy link

eflatz commented Jul 23, 2018

gesturesEnabled didn't work for me ("react-navigation": "^2.3.1") but swipe enable did.

I have a case with parent TabNavigator and StackNavigator as a child: https://stackoverflow.com/questions/48114810/react-native-disable-swiping-stacknavigator-in-tabnavigator?rq=1

MyStack.navigationOptions = ({navigation}) => {
  return {
    swipeEnabled: false
  }
}

@gbalduzzi
Copy link

If anyone is having the same problem in the newer versions, you can set the default navigation options for all the screens in a stack with defaultNavigationOptions:

const MainStack = createStackNavigator({
  Dashboard: DashboardScreen,
},
{
  initialRouteName: "Dashboard",
  defaultNavigationOptions: {
    gesturesEnabled: false
  }
})

@vmcruz
Copy link

vmcruz commented Mar 23, 2019

The gesturesEnabled: false is not working for me on Android Emulator. This worked instead:

const AppStack = createStackNavigator({
  Welcome: {
    screen: Welcome,
    navigationOptions: () => ({
      gestureResponseDistance: {
        horizontal: -1,
        vertical: -1,
      },
    }),
  },
});

It is still a hack, but at least I was able to disable this behavior. This issue was causing me troubles while performing E2E testing with Detox on the .swipe action.

@OshaFoster
Copy link

I would like to show a toast when the user swipes to navigate back, to let them know there changes will be lost. Any suggestions on how I could do that?

@Beats0
Copy link

Beats0 commented Mar 26, 2019

not work for IphoneX ?

@AnilkumarDO
Copy link

Not working in iOS and Android gesturesEnabled: false

@sangampandey
Copy link

If anyone is having the same problem in the newer versions, you can set the default navigation options for all the screens in a stack with defaultNavigationOptions:

const MainStack = createStackNavigator({
  Dashboard: DashboardScreen,
},
{
  initialRouteName: "Dashboard",
  defaultNavigationOptions: {
    gesturesEnabled: false
  }
})

This solution works for me on "react-navigation": "^3.3.2"

@Neha0595
Copy link

It works for me if i didn't wrap "gestureEnabled: false" in card stack

@nikola-kolosek
Copy link

What if I wanted do disable and enable it dynamically?
For example, I have a component that is a route inside a stack. I want the user to be able to go back if they want to, but not if the component is fetching some information from the server. When the component finishes fetching, enable going back once again.

@lucaspelloni2
Copy link

    [__SCREENS.AUTHENTICATION]: {
      screen: ({navigation}: NavigationProps) => (
        <AuthMask screen={AuthScreenType.SOCIAL} navigation={navigation} />
      ),
      path: __SCREENS.AUTHENTICATION,
      navigationOptions: ({navigation}: NavigationProps) => ({
        headerLeft: <MyView />,
        headerTitle: <StepTracker stepArray={firstStep} />,
        headerRight: <HeaderRightSide navigation={navigation} />,
        gesturesEnabled: false,
      }),
    },

Worked for me as well !

@salujaharkirat
Copy link

in react navigation 4, navigationOptions has been changed to defaultNavigationOptions

@ssathishppm
Copy link

in ios when using below code, it's loading a white background. I want to disable the swipe option

const MainStack = createStackNavigator({
Dashboard: DashboardScreen,
},
{
initialRouteName: "Dashboard",
defaultNavigationOptions: {
gesturesEnabled: false
}
})

@ssathishppm
Copy link

Anyone know how to fix above ?

@Hemantkml
Copy link

import React, {Component} from 'react';
import {createAppContainer} from 'react-navigation';

import {createStackNavigator} from 'react-navigation-stack';
import LoginScene from '../src/LoginScene';
import SignUpScene from '../src/SignUpScene';
import TabBar from '../src/TabBar';
import Header from '../src/Common/Header';
import WelcomeScene from './scene/WelcomeScene';
import TutorialScene from '../TutorialScene';
class AppNavigation extends Component {
constructor(props) {
super(props);
this.state = {};
}

render() {
return ;
}
}
const MainNavigator = createStackNavigator(
{
TutorialScene: {screen: TutorialScene},
WelcomeScene: {screen: WelcomeScene},
SignUpScene: {screen: SignUpScene},
LoginScene: {screen: LoginScene},
TabBar: {screen: TabBar},
Header: {screen: Header},
},
{
defaultNavigationOptions: {
gesturesEnabled: false,
},
headerMode: 'none',
},
);

const AppNavigator = createAppContainer(MainNavigator);
export default AppNavigation;

@kopax
Copy link

kopax commented Feb 10, 2020

I see a lot of gesturesEnabled (plural) here, what worked for me is gestureEnabled={false} (singular) on my Stack.Navigator with react-navigation 5.

@CyxouD
Copy link

CyxouD commented Feb 10, 2020

@nikola-kolosek control it with static navigationOptions by passing navigation params

@santanuyogi
Copy link

I see a lot of gesturesEnabled (plural) here, what worked for me is gestureEnabled={false} (singular) on my Stack.Navigator with react-navigation 5.

Ahh... thank you so much. That worked for me when other solutions hadn't.

@NilPuig
Copy link

NilPuig commented Apr 19, 2020

'gesturesEnabled' will be removed in a future version. Use 'gestureEnabled' instead:

  ResolveAuth: {
    screen: ResolveAuthScreen,
    navigationOptions: {
      gestureEnabled: false,
    },
  },

@khaledBou
Copy link

function MyStack() {
  return (
    <Stack.Navigator
      initialRouteName="Home"
      headerMode="screen"
      screenOptions={{
        headerTintColor: 'white',
        headerStyle: {backgroundColor: 'tomato'},
      }}
      options={{
        gestureEnabled: false,   // <------------------- ADD THIS
      }}>
      <Stack.Screen name="Home" component={Home} />
      <Stack.Screen name="HomeDetails" component={HomeDetails} />
    </Stack.Navigator>
  );
}

@Youn-ha
Copy link

Youn-ha commented Jul 14, 2020

Hello, nothing mentioned in this thread worked for me.
So I checked out official docs of React Navigation, and found this out.

https://reactnavigation.org/docs/stack-navigator/#example

/* -------------- example1 -------------- */

    <Stack.Navigator initialRouteName="Home">
      <Stack.Screen
        name="Home"
        component={Home}
        options={{
          gestureEnabled: false,
        }}
      />
      <Stack.Screen
        name="Profile"
        component={Profile}
        options={{
          gestureEnabled: false,
        }}
      />
      <Stack.Screen
        name="Settings"
        component={Settings}
        options={{
          gestureEnabled: false,
        }}
      />
    </Stack.Navigator>

First, I had to give gestureEnabled: false option to screen, NOT NAVIGATOR. (Well, official docs did like this! and it didn't work for me when I gave this option to navigator instead of screen...)
Second, I had to give the option to every Stack in navigator that I want to disable swipe gesture.
Third, I had to give the option also to RootStack.Screen the navigator is involved too! Like the example under.

/* -------------- example2 -------------- */

    <NavigationContainer>
      <RootStack.Navigator headerMode="none" initialRouteName="TabNavigator">
        <RootStack.Screen
          name="SignUpNavigator"
          component={SignUpNavigator}
        />
        <RootStack.Screen
          name="LoginNavigator"
          component={LoginNavigator}
        />
        <RootStack.Screen
          name="TabNavigator"
          component={TabNavigator}
        />
        <RootStack.Screen
          name="SettingsNavigator"
          component={SettingsNavigator}
          // Given that 'SettingsNavigator' is the one involving screens above (screens in example1 !!)
          options={{ gestureEnabled: false }}
        />
      </RootStack.Navigator>
    </NavigationContainer>

Hope this can be a nice help to somebody.

@harveyappleton
Copy link

harveyappleton commented Aug 11, 2020

Following up from @Youn-ha comment - you can disable it across the whole stack navigator by doing the following.

<Stack.Navigator
  screenOptions={{
  headerShown: false,
 gestureEnabled: false,
 }}>
{/* screens here */}
</Stack.Navigator>

Hope this helps someone out there 😁

@AroldoGoulart
Copy link

AroldoGoulart commented Sep 15, 2020

Example of route definition with gesturesEnabled: false

Example: {
    name: 'Example Screen',
    screen: ExampleView
    navigationOptions: {
        gesturesEnabled: false,
    },
},

For me, for some reason it does not work if I wrap gesturesEnabled: false with cardStack.

This worked perfectly, TY!

@AlekseyPimenov
Copy link

AlekseyPimenov commented Oct 12, 2020

iOS 14, all ways above not working for me =(
RN: 0.63.1
React-navigation: ~5.7.1
Does someone know about it?

@andikare
Copy link

me to not work
RN: 0.63.1
` return (
<Stack.Navigator initialRouteName="Login" screenOptions={{
headerShown: false,
gestureEnabled: false
}}>
<Stack.Screen options={{
headerStyle: {
backgroundColor: colorbirugelap,
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},

  }} name="Login" component={Login} />
  {/* <Stack.Screen name="Login" component={Login} /> */}
  <Stack.Screen name="Dasboard" component={Dasboard} />
  <Stack.Screen name="data2" component={data2} />
  <Stack.Screen name="data3" component={data3} />

</Stack.Navigator>`

@antonioreyna
Copy link

not working for ios14

@rawatnaresh
Copy link

is there any way to override this swipe behaviour for android and ios? I would like to navigate them to a particular screen on swipe back.

@gaurav-psych
Copy link

Not working for ios14 .

@jwhitty1
Copy link

jwhitty1 commented Nov 8, 2020

Following up from @Youn-ha comment - you can disable it across the whole stack navigator by doing the following.

<Stack.Navigator
  screenOptions={{
  headerShown: false,
 gestureEnabled: false,
 }}>
{/* screens here */}
</Stack.Navigator>

Hope this helps someone out there 😁

ANYONE LOOKING FOR AN ANSWER THAT WORKS TRY THIS!!

@MannySauce
Copy link

Not working for iOS 14 - 14.2

@Kernael
Copy link

Kernael commented Nov 26, 2020

Be careful, it's gestureEnabled, not gesturesEnabled

@jbromberg
Copy link

Nothing here seems to be working on iOS 14.3. Setting the gestureEnabled option on a screen to false still allows the user to swipe back.

@Charpell
Copy link

Charpell commented Apr 9, 2021

If anyone is still having this issue, it could mean you are having a deep nested navigation ion your code.
So you'd have to repeat the gestureEnabled: false for both parent and children

@greengeeko32
Copy link

If anyone is still having this issue, it could mean you are having a deep nested navigation ion your code.
So you'd have to repeat the gestureEnabled: false for both parent and children

This works to me, thanks.

@github-actions
Copy link

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

@thanhluantl2304
Copy link

I found the problem. I faced this problem when I try to set this with the PUSH stack, not the NAVIGATE �stack

@github-actions
Copy link

github-actions bot commented Oct 1, 2021

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

@fedeerbes
Copy link

for those who are looking for a way to dynamically disable the gestureEnabled prop.

this worked for me

<Stack.Navigator
      screenOptions={{
        headerShown: false,
        ...TransitionPresets.SlideFromRightIOS,
        gestureEnabled: true,
      }}>
      <Stack.Screen name="SwapScreen" component={SwapScreen} />
      <Stack.Screen
        name="ConfirmationSwap"
        component={ConfirmationSwapScreen}
      />
    </Stack.Navigator>

for example inside of SwapScreen or a component inside of the screen you can do the following

useEffect(
    () => navigation.getParent()?.setOptions({ gestureEnabled: CONDITION }),
    [navigation, CONDITION],
  );

@github-actions
Copy link

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

@svmszcck
Copy link

svmszcck commented May 2, 2022

The solution is to set gestureEnabled to false in the parent Stack Navigator(not current Stack Navigator) screen and setting gestureEnabled to true for the screens which need the gesture in the current stack or directly in the current stack navigator. Worked for me with React Navigation 5.

This is a little bit hacky but working for me:

Parent Stack => Current Stack => Screen 1, Screen 2, Screen 3...

Here set gestureEnabled to false in Parent Stack Navigator's screen(which is Current Stack), set gestureEnabled to true in
Current Stack Navigator options and then set gestureEnabled to false in the specific screens(for ex. Screen 2 only).

@github-actions
Copy link

github-actions bot commented May 2, 2022

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

@pruthvirajkarurcodewave
Copy link

pruthvirajkarurcodewave commented Sep 21, 2022

nothing worked for me. But @fedeerbes solution of disabling it dynamically worked.

useEffect(
    () => navigation.getParent()?.setOptions({ gestureEnabled: CONDITION }),
    [navigation, CONDITION],
  );

@github-actions
Copy link

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

@UrosTheDev
Copy link

The solution is to set gestureEnabled to false in the parent Stack Navigator(not current Stack Navigator) screen and setting gestureEnabled to true for the screens which need the gesture in the current stack or directly in the current stack navigator. Worked for me with React Navigation 5.

This is a little bit hacky but working for me:

Parent Stack => Current Stack => Screen 1, Screen 2, Screen 3...

Here set gestureEnabled to false in Parent Stack Navigator's screen(which is Current Stack), set gestureEnabled to true in Current Stack Navigator options and then set gestureEnabled to false in the specific screens(for ex. Screen 2 only).

This worked for me. React Navigation 5.

So, the main/root stack navigator has a nested navigator KYCNavigation. There you put this code:

<Stack.Screen
name="kyc-nav"
component={KYCNavigation}
options={{ gestureEnabled: false }}
/>

Then in the KYCNavigation stack you place this code:

<Stack.Navigator headerMode="none" screenOptions={{ gestureEnabled: true }}>

After that for every screen you can specify behavior like this:

<Stack.Screen
name="passport-verification-info"
component={withLocalization(PassportVerificationInfoScreen)}
options={{
gestureEnabled: true // if true will allow swipe back, if false will not allow swipe back
}}
/>

@github-actions
Copy link

github-actions bot commented Dec 9, 2022

Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests