[General] Allow gesture detector to have multiple children#3981
[General] Allow gesture detector to have multiple children#3981j-piasecki merged 5 commits intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request enables GestureDetector to accept multiple children for non-native gesture handlers, extending functionality beyond the previous single-child limitation. The implementation calculates bounding boxes that encompass all children across web, iOS, and Android platforms, while maintaining the restriction that native gesture handlers can only be attached to a single child view.
Changes:
- Implemented bounding box calculation for multiple children on web (using
display: contentselements), iOS/Android native shadow nodes, and Android hit testing - Added validation to prevent attaching native gesture handlers when multiple children are present
- Refactored web delegate code to use a centralized style-setting helper method
- Updated
findNodeHandleon web to stop traversal atdisplay: contentsnodes with multiple children - Removed duplicate child count validation checks in the web detector component
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/react-native-gesture-handler/src/web/utils.ts | Added getEffectiveBoundingRect function to calculate bounding box for display: contents elements with multiple children |
| packages/react-native-gesture-handler/src/web/tools/PointerEventManager.ts | Updated to use new getEffectiveBoundingRect utility |
| packages/react-native-gesture-handler/src/web/tools/GestureHandlerWebDelegate.ts | Refactored style-setting code into setViewStyle helper and updated to use getEffectiveBoundingRect |
| packages/react-native-gesture-handler/src/v3/detectors/HostGestureDetector.web.tsx | Added validation for native handlers with multiple children and removed duplicate single-child checks |
| packages/react-native-gesture-handler/src/findNodeHandle.web.ts | Updated to stop traversal at display: contents nodes with multiple children |
| packages/react-native-gesture-handler/shared/shadowNodes/.../RNGestureHandlerDetectorShadowNode.cpp | Implemented bounding box calculation for multiple children and adjusted child positions relative to detector origin |
| packages/react-native-gesture-handler/apple/RNGestureHandlerDetector.mm | Added assertions to prevent multiple children when native handlers are attached |
| packages/react-native-gesture-handler/android/.../RNGestureHandlerDetectorView.kt | Added assertions to prevent multiple children when native handlers are attached |
| packages/react-native-gesture-handler/android/.../GestureHandler.kt | Updated hit testing logic to check all children instead of just the first one |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
...es/react/renderer/components/rngesturehandler_codegen/RNGestureHandlerDetectorShadowNode.cpp
Show resolved
Hide resolved
...ve-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt
Show resolved
Hide resolved
akwasniewski
left a comment
There was a problem hiding this comment.
If we allow this, I think we should add a style prop to the detector which would be applied to the underlying view.
|
@akwasniewski That would defeat the purpose of calculating the bounding box. If someone sets It could also be confusing - in the example from the PR description, there's a gap between the two detector children. Gestures ARE NOT recognized on that gap. If the gesture detector had a background set, it could be understood as a surface for handling gestures. It's possible to accomplish that in this approach by wrapping children with a view and styling that. If we went with styling the detector, I'm not sure the current behavior is easily replicable. |
Ok, you are right, it would overcomplicate things. |
m-bert
left a comment
There was a problem hiding this comment.
I can see one limitation that I'm not sure if we can get rid of - it is not possible to trigger gesture(s) on all views at the same time. e.g. in the test code if you tap both boxes at the same time, "tapped" will be displayed only once.
...ler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerDetectorView.kt
Outdated
Show resolved
Hide resolved
...ve-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt
Outdated
Show resolved
Hide resolved
…m/swmansion/gesturehandler/react/RNGestureHandlerDetectorView.kt Co-authored-by: Michał Bert <63123542+m-bert@users.noreply.github.com>
Is that a limitation? IMO, it's expected that the gesture will not activate twice. If you need that, you can use two separate ones. |
m-bert
left a comment
There was a problem hiding this comment.
Is that a limitation? IMO, it's expected that the gesture will not activate twice. If you need that, you can use two separate ones.
I think this is something that one might expect since all views are under one detector. But I agree that in that case you should have separate gestures.
Description
Updates
GestureDetectorto accept more than a single child when using gestures other than native.On native platforms, this is done by changing the layout of the detector node from matching its only child to calculating the bounding box of all children. The logic on Android needed to be updated so it tries to hit test every detector child instead of just the first one.
On web, this is done similarly, but since the detector node doesn't produce a box, the bounding box is calculated dynamically. This needed some updates in the custom
findNodeHandleimplementation to stop atdisplay: contentsnodes which have more than one child.Test plan
And example apps