Description
On Android with New Architecture enabled, there is a major issue with touch event distribution. If a first finger is placed on a parent container (background), a second finger interacting with a GestureDetector (like a PanGesture) will trigger onBegin, but onUpdate will never fire.
The first finger "locks" the touch stream, preventing subsequent pointers from sending continuous event data to other handlers in the hierarchy. This effectively breaks all multi-touch interactions where one finger acts as a reference or is simply resting on the screen.
Steps to reproduce
### Packages version
react: 19.2.0
react-native: 0.83.1
react-native-gesture-handler: 2.30.0
react-native-reanimated: 4.2.1
### Platforms
[X] Android (Fabric enabled)
[ ] iOS
### Steps to reproduce
Use the provided example code on an Android device with New Architecture.
First: Press and hold a finger anywhere on the background.
Second: While keeping the first finger down, try to drag the purple box with a second finger.
Observed Behavior: The box does not move. onBegin is triggered (can be seen via logs), but onUpdate is never called as long as the first finger is touching the background.
Expected Behavior: Each pointer should be handled independently. The second finger should be able to move the box regardless of where the first finger is placed.
import {StyleSheet} from 'react-native'
import {Gesture, GestureDetector, GestureHandlerRootView} from 'react-native-gesture-handler'
import Animated, {useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'
const END_POSITION = 200
const App = () => {
const onLeft = useSharedValue(true)
const position = useSharedValue(0)
const panGesture = Gesture.Pan()
.onBegin(() => console.log('onBegin called'))
.onUpdate(e => {
if (onLeft.value) {
position.value = e.translationX
} else {
position.value = END_POSITION + e.translationX
}
})
.onEnd(() => {
if (position.value > END_POSITION / 2) {
position.value = withTiming(END_POSITION, {duration: 100})
onLeft.value = false
} else {
position.value = withTiming(0, {duration: 100})
onLeft.value = true
}
})
const animatedStyle = useAnimatedStyle(() => ({
transform: [{translateX: position.value}]
}))
return (
<GestureHandlerRootView style={styles.flex1}>
<GestureDetector gesture={panGesture}>
<Animated.View style={[styles.box, animatedStyle]} />
</GestureDetector>
</GestureHandlerRootView>
)
}
const styles = StyleSheet.create({
flex1: {
flex: 1
},
box: {
height: 120,
width: 120,
backgroundColor: '#b58df1',
borderRadius: 20,
marginBottom: 30
}
})
export default App
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/alexandre-autran/e46cf714bc4e558493cb963bc78d1500
Gesture Handler version
2.30.0
React Native version
0.83.1
Platforms
Android
JavaScript runtime
None
Workflow
React Native (without Expo)
Architecture
New Architecture (Fabric)
Build type
None
Device
Real device
Device model
No response
Acknowledgements
Yes
Description
On Android with New Architecture enabled, there is a major issue with touch event distribution. If a first finger is placed on a parent container (background), a second finger interacting with a GestureDetector (like a PanGesture) will trigger onBegin, but onUpdate will never fire.
The first finger "locks" the touch stream, preventing subsequent pointers from sending continuous event data to other handlers in the hierarchy. This effectively breaks all multi-touch interactions where one finger acts as a reference or is simply resting on the screen.
Steps to reproduce
### Packages version
react: 19.2.0
react-native: 0.83.1
react-native-gesture-handler: 2.30.0
react-native-reanimated: 4.2.1
### Platforms
[X] Android (Fabric enabled)
[ ] iOS
### Steps to reproduce
Use the provided example code on an Android device with New Architecture.
First: Press and hold a finger anywhere on the background.
Second: While keeping the first finger down, try to drag the purple box with a second finger.
Observed Behavior: The box does not move. onBegin is triggered (can be seen via logs), but onUpdate is never called as long as the first finger is touching the background.
Expected Behavior: Each pointer should be handled independently. The second finger should be able to move the box regardless of where the first finger is placed.
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/alexandre-autran/e46cf714bc4e558493cb963bc78d1500
Gesture Handler version
2.30.0
React Native version
0.83.1
Platforms
Android
JavaScript runtime
None
Workflow
React Native (without Expo)
Architecture
New Architecture (Fabric)
Build type
None
Device
Real device
Device model
No response
Acknowledgements
Yes