react-native-screens: Touch events do not work when multiple screens are active on Android

I added a way to have transparent scenes in react-navigation a while back to support dialogs (https://github.com/react-navigation/react-navigation-stack/blob/master/src/views/StackView/StackViewCard.js#L35). It keeps all screens active in the stack but this seems to break touch events on Android because of the logic here: https://github.com/kmagiera/react-native-screens/blob/master/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.java#L189

The react-navigation code is basically this:

const modalNavigatorConfig = {
  initialRouteName: 'app',
  mode: 'modal',
  headerMode: 'none',
  transparentCard: true, // <- The option for transparent card
  defaultNavigationOptions: {
    gesturesEnabled: false,
  },
  transitionConfig: () => ({
    transitionSpec: {
      duration: 300,
      easing: Easing.inOut(Easing.ease),
      timing: Animated.timing,
    },
    screenInterpolator: sceneProps => {
      const { position, scene } = sceneProps;
      const { index } = scene;

      const opacity = position.interpolate({
        inputRange: [index - 1, index],
        outputRange: [0, 1],
      });

      return { opacity };
    },
  }),
};

const ModalStack = createAppContainer(
  createStackNavigator(
    {
      app: {
        screen: RootStack,
      },
      { screen: SomeOtherRoute },
    },
    modalNavigatorConfig,
  ),
);

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 32
  • Comments: 43 (4 by maintainers)

Commits related to this issue

Most upvoted comments

I did a little expirement and changed this line from Screen.java :

@Override
public PointerEvents getPointerEvents() {
    return mTransitioning ? PointerEvents.NONE : PointerEvents.AUTO;
}

to :

@Override
public PointerEvents getPointerEvents() {
    return PointerEvents.AUTO;
}

This seems to resolve the issue as all the views will be able to receive touch events even when “transitioning” and I haven’t seen any side effects when it comes to performance. I might make a PR with a config to override the default behaviour of this method…

Think I’m seeing a similar issue on iOS: when navigating back to a previous screen in a stack that has transparentCard set, the screen doesn’t respond to touch events. Had a poke around with the Element Inspector and it seems that the component tree is “StackViewLayout > ScreenContainer” after navigating back, compared to “StackViewLayout > SceneView > [ Screen ]” initially. Navigation gestures still work, screen focus events still trigger and navigating from the screen via code is fine. Will investigate further and try to get a snack up and running asap

+1 We recently upgraded to React Navigation 3.X and it looks like all 3.X compatible versions of react-native-screens have this issue. We use transparentCard for our dialog system as well.

I change the import of the StackNavigator from import { createStackNavigator } from 'react-navigation-stack'; to the one that say this library import createNativeStackNavigator from 'react-native-screens/createNativeStackNavigator'; and it’s working for me

I had same issue, reinstalling the react-native-screens resolved the issue.

Still looking for a solution that works on Android…

After upgrading to Expo 33, my original issue no longer occurred on iOS. I did however have a problem with nested ScrollViews/FlatLists—I could scroll them, but the list items were not tappable. I resolved that by adding keyboardShouldPersistTaps="always" to the nested ScrollViews/FlatLists.

I’m still facing issues on Android

TouchableOpacity components are not responding to touch in any nested screens on Android when using transparentCard : true within the createStackNavigator config.

any news on this one?

shouldn’t this kind of stuff handled in navigation itself? using pointerEvents prob for example.

We have the same problem with useScreens() + transparentCard: true

I found this commit caused a similar problem in the FluidTransitions package. Since that change was introduced in alpha-18, I use alpha-17 to work around the problem.

react-native-screens disable touch interaction for the duration of screen transition […] The way we detect screen transition now is when there are two or more active screens

This seems contradictory to the documentation:

It it possible to have as many active children as you’d like but in order for the component to be the most effictent we should keep the number of active screens to the minimum.

react-native-screens disable touch interaction for the duration of screen transition (so that you can’t interact with buttons on the screen that is going away). The way we detect screen transition now is when there are two or more active screens. I believe that is the case when you have a transaprent dialog too. This would need to be changed in screen implementation (both on Android and iOS)

@emeraldsanto’s solution worked on Android

For iOS, I fixed it by disabling the logic which disables interactions during a transition. I did this by going to RNSScreenContainer.m and changed

screen.userInteractionEnabled = NO;

to

screen.userInteractionEnabled = YES;

@15matias15’s solution (to use the in-package createNativeStackNavigator) is the right solution for now, but it breaks when using react-navigation-stack 2.0 (currently in alpha). I opened #173 to track

I’m also facing this issue.

Configuration

Expo SDK 32 React Native Screens imported from Expo React Navigation 3.9.1 1 tab navigator with 4 tabs

To reproduce:

  1. Open app - tab 1 is open by default
  2. Navigate to tab 2 - everything on tab 2 is responsive as expected
  3. Navigate back to tab 1 - everything still responsive
  4. Navigate back to tab 2 - screen is completely unresponsive. SceneView + children have been replaced by ScreenContainer --> RNSScreenContainer

Resolution

Remove react-native-screens until the issue is fixed 😦

@kmagiera What was the reason for moving touch event handling inside rn-screens vs using the pointerEvents from JS that react-navigation sets like it was before?

@ovy9086 - let’s keep this all within this thread as it’s the same underlying issue.

@ovy9086’s other post below


When using react-native-screens with react-navigation 3 , enabling both useScreens() and transparentCard in the createStackNavigator options causes weird issues.

On iOS, if having more than 3 routes in the StackNavigator, when going back to the 2nd screen, you will not be able to interact the view anymore. Apparently something blocks it. On Android, the 2nd screen is not clickable from the first time you navigate to it.

Here is a repo to reproduce this : https://github.com/ovy9086/react-nav-transparent-card-bug

@GfxKai I’m running into the same issue exactly, yet I haven’t been able to replicate it in a snack. I can confirm that the component tree ends in ScreenContainer, and that toggling transparentCard to false on the StackNavigator fixes the component tree and resolves the unresponsiveness.