[Pressable] Pressed state is not visible for quick taps inside ScrollView on iOS
Description
I observe a different order of events inside Pressable if it's inside a RNGH ScrollView, causing the pressed state to not be visible.
https://github.com/user-attachments/assets/d073f9e8-1c07-4858-bd6c-6c6f5a101a8d
Steps to reproduce
Shown on the video inside the description
A link to a Gist, an Expo Snack or a link to a repository based on this template that reproduces the bug.
https://gist.github.com/gigobyte/46790a144ceb6ec66609c732a6c103b8
Gesture Handler version
2.27.1
React Native version
0.79.0
Platforms
iOS
JavaScript runtime
None
Workflow
React Native (without Expo)
Architecture
New Architecture (Fabric)
Build type
None
Device
iOS simulator
Device model
No response
Acknowledgements
Yes
Hey! 👋
The issue doesn't seem to contain a minimal reproduction.
Could you provide a snack or a link to a GitHub repository under your username that reproduces the problem?
Hey, this is actually expected behaviour.
On iOS, inside scroll list, there's a system-enforced ~200ms activation delay, which prevents children of the scroll list from activating until they've been pressed down for 200ms without the list moving.
The original RN Pressable ignores this 200ms delay, which is invalid, and doesn't follow the conventional behaviour of other iOS components.
The reason this behaviour does not occur on Android is that Android puts the activation burden on the scroll list element instead of the button element. Instead of waiting 200ms for the button to activate, a movement threshold is put on the list, once the threshold is reached, no child of the list can activate until the scroll list stops moving.
I assume this is the property you're describing:
// apple/Handlers/RNNativeViewHandler.mm
scrollView.delaysContentTouches = YES;
In that case, is it possible to expose control of that flag? In our case we are upgrading from an old version of RNGH, not the original react-native Pressable, and we didn't observe the delay before.
is it possible to expose control of that flag
Will look into that, but there's a chance that'll break a lot of logic.
we didn't observe the delay before
I just checked, and you're right. While the onPress behaviour didn't change in the new version, the onPressIn no longer fires on the first touch input, and onPressOut no longer fires on cancellation of the first touch input.
This will be fixed.
Tests
onPress* callbacks |
onPress / functional styling |
|---|---|
Branch with the test code visible on the video:
https://github.com/software-mansion/react-native-gesture-handler/tree/%40latekvo/compare-old-new-original-pressables
Will look into that, but there's a chance that'll break a lot of logic.
We've been running with the flag disabled for 1 month now without any issues on a large userbase. This is fyi for other people also willing to patch it.