[android] fixed experimental pointers breaking after pan#3801
Conversation
|
But you're very likely right about it not being cleaned. I think we should be calling |
j-piasecki
left a comment
There was a problem hiding this comment.
Ah, forgot to click the thingy 🤦
Ok, now it makes sense, Thank you. |
j-piasecki
left a comment
There was a problem hiding this comment.
This looks to be a good direction!
In a project using experimental pointer events, activation of the pan gesture stopped recognition of Js pointer events. This PR should resolve this issue. I believe the error is due to the fact that `onCancel` calls rootView.onChildStartedNativeGesture, which sets the `UNSET_CHILD_VIEW_ID` in JSPointerDispatcher.kt to current view tag, which is never cleared. This blocks pointer events from being called, as the pointer dispatcher thinks that some child is handling a native gesture. I added cleanup when all fingers have been lifted. Enable experimental pointer events: https://reactnative.dev/blog/2022/12/13/pointer-events-in-react-native#enable-feature-flags. Use the following code to test the component: <details> ```ts import React from 'react'; import { Text, Pressable, 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; function App(): React.JSX.Element { const [count, setCount] = React.useState(0); const [pressCount, setPressCount] = React.useState(0); const onLeft = useSharedValue(true); const position = useSharedValue(0); const panGesture = Gesture.Pan() .onUpdate((e) => { if (onLeft.value) { position.value = e.translationX; } else { position.value = END_POSITION + e.translationX; } }) .onEnd((e) => { 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.container}> <Pressable style={{ padding: 16, backgroundColor: '#aa0044' }} onPointerDown={() => setCount(n => n + 1)} onPressIn={() => setPressCount(n => n + 1)} > <Text style={{ color: 'black' }}>Press me</Text> </Pressable> <Text style={{ marginBottom: 16, color: 'black' }}> pointer: {count} -- press: {pressCount} </Text> <GestureDetector gesture={panGesture}> <Animated.View style={[styles.box, animatedStyle]} /> </GestureDetector> </GestureHandlerRootView> ); } const styles = StyleSheet.create({ container: { padding: 64, flex: 1, }, box: { height: 120, width: 120, backgroundColor: '#b58df1', borderRadius: 20, marginBottom: 30, }, }); export default App; ``` </details> If you have experimental pointer events turned on clicking on the upper pressable should increase both counters even after using pan gesture on the box below. Before this PR, after panning, only one counter worked.
Description
In a project using experimental pointer events, activation of the pan gesture stopped recognition of Js pointer events. This PR should resolve this issue.
Fix
I believe the error is due to the fact that
onCancelcalls rootView.onChildStartedNativeGesture, which sets theUNSET_CHILD_VIEW_IDin JSPointerDispatcher.kt to current view tag, which is never cleared. This blocks pointer events from being called, as the pointer dispatcher thinks that some child is handling a native gesture. I added cleanup when all fingers have been lifted.Test plan
Enable experimental pointer events: https://reactnative.dev/blog/2022/12/13/pointer-events-in-react-native#enable-feature-flags.
Use the following code to test the component:
Details
If you have experimental pointer events turned on clicking on the upper pressable should increase both counters even after using pan gesture on the box below. Before this PR, after panning, only one counter worked.