[Native] Fix Touchable behavior when nested within gesture handlers#4106
Merged
j-piasecki merged 2 commits intomainfrom Apr 23, 2026
Merged
[Native] Fix Touchable behavior when nested within gesture handlers#4106j-piasecki merged 2 commits intomainfrom
Touchable behavior when nested within gesture handlers#4106j-piasecki merged 2 commits intomainfrom
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes nested Touchable interactions when used inside/alongside other gesture handlers, addressing interruption behavior and an Android-specific stale touch-target cleanup issue.
Changes:
- Add
disallowInterruption: trueto the v3Touchablenative wrapper configuration. - On Android, proactively dispatch a synthetic
ACTION_CANCELto the subtree when a new touch stream starts (ACTION_DOWN) to clear potentially stale touch-target state. - Add a new example screen demonstrating nested gestures + touchables and register it in the new API examples list.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/react-native-gesture-handler/src/v3/components/Touchable/Touchable.tsx | Sets disallowInterruption: true on the wrapped button to avoid unexpected interruption when nested with other gestures. |
| packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootView.kt | Dispatches a synthetic ACTION_CANCEL at the start of a new stream to pre-clean stale touch-target state on Android. |
| apps/common-app/src/new_api/tests/nestedTouchables/index.tsx | Adds a new manual repro/example for nested touchables + tap gestures and an on-screen event log. |
| apps/common-app/src/new_api/index.tsx | Registers the new “Nested touchables” example in the new API examples list. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
j-piasecki
added a commit
that referenced
this pull request
Apr 23, 2026
## Description 1. Adds `stopPropagation` call to event handlers in `Touchable` so only the inner-most one triggers the active animation. 2. Changes when buttons without `shouldActivateOnStart` (so `Touchable`) activate - instead of doing it on pressDown, now it happens during pressUp. This ensures that all other handlers have been extracted and can be canceled/can cancel `Touchable` correctly. 3. Behavior for buttons with `shouldActivateOnStart` (other buttons) shouldn't change after this PR, but the proper `shouldActivateOnStart` implementation is still to be done. ## Test plan Tested on the example from #4106
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
See #4097
Fixes interactions of nested touchables/gestures:
disallowInterruption: trueprop, which caused it to misbehave when used alongside other gesturesViewGroup. Since RNGH can start intercepting events mid-stream, this list could contain stale values. The OS, trying to clean it up, would dispatch a syntheticACTION_CANCELevent, which resulted in the touchable working every other time it's been pressed. To fix that, we do the cleanup by ourselves, by dispatching a syntheticACTION_CANCELevent before the new event stream starts.Test plan
Added a new example
This doesn't work correctly on web, but it didn't work before either.