androidreact-nativetouchableopacity

react-native: TouchableOpacity'a onPress() doesn't get called in modals on slower Android devices


On older and slower Android devices, the onPress() method on TouchableOpacity might not be called even though the button is pressed and you can see the opacity effect on the view.

What's weird is that it's statistical, on a Samsung Galaxy A8 around 20% of the time the press did work, on my Pixel 6 Pro the press works 100% of the time.

onPressIn() is always called but onPress() is uncertain.


Solution

  • tl;dr Don't use react-native-modals, it's buggy, find an alternative (I use react-native-modal instead)

    I spent a while trying to figure out why onPressIn() was called successfully while onPress() wasn't, I read the logic in react-native's code, which uses the Gesture Responder System on determining whether a callback should be called.

    When the press works, those are the signals I see from the touch events system:

    RESPONDER_GRANT // (touch detected on View, causes onPressIn() to be called)
    
    DELAY // (can determine whether we want onPress() or onPressLong())
    
    RESPONDER_RELEASE // (finger lifted, depending on DELAY now onPress() / onPressOut() are called)
    

    and when the press doesn't work:

    RESPONDER_RELEASE
    
    RESPONDER_TERMINATED // (nothing happens)
    

    RESPONDER_TERMINATED means that someone else took control of the gesture responder system, why does it happen? I'm not sure, I couldn't figure out why react-native-modals caused it to happen but eventually I tried using react-native-modal instead and it acted correctly, nothing hijacked my presses!