waitFor and simultaneousHandlers do not work with LongPressGestureHandler and PanGestureHandler
See original GitHub issueDescription
Adding the option that PanGestureHandler waitFor a LongPressGestureHandler does not work, the PanGestureHandler activates directly. And once LongPressGestureHandler activates, PanGestureHandler deactivates even with simultanousHandler setup according to docs.
Let me know if I have done anything incorrectly, but I have only followed the docs to the best of my ability combining waitFor and simultaneousHandlers…
Screenshots
Steps To Reproduce
- Create a new blank project with expo (
expo init
) - Install Reanimated 2 and Gesture handler (
expo install react-native-gesture-handler && npm install react-native-reanimated@2.0.0-rc.0
) - Copy and paste in the babel plugin for expo reanimated (
plugins: ['react-native-reanimated/plugin'],
) - Download any image to project-dir/assets/example.jpg
- Copy and paste the below code snippet into the App.js and start the expo dev client (
expo start -c
) - Try and drag the image and longpress - you will see it is reversed from what is expected.
Expected behavior
The PanGestureHandler should waitFor the LongPressGestureHandler to exit the “BEGIN” state before activating, and stay activated once the LongPressGestureHandler activates according to simultaneousHandlers.
Actual behavior
The PanGestureHandler ignores waitFor and simultaneousHandler and activates before LongPressGestureHandler, and deactives once LongPressGestureHandler activates.
Snack or minimal code example
import React from "react";
import { View, Image } from "react-native";
import {
PanGestureHandler,
LongPressGestureHandler,
ScrollView,
} from "react-native-gesture-handler";
import Animated, {
useAnimatedStyle,
useAnimatedGestureHandler,
useSharedValue,
} from "react-native-reanimated";
export default function App() {
const imageSize = 50;
const longPressRef = React.createRef();
const panRef = React.createRef();
const y = useSharedValue(0);
const x = useSharedValue(0);
const onGestureEvent = useAnimatedGestureHandler({
onStart: (event, ctx) => {
ctx.offsetX = x.value;
},
onActive: (event, ctx) => {
y.value = event.translationY;
x.value = event.translationX + ctx.offsetX;
},
});
const style = useAnimatedStyle(() => ({
position: "absolute",
top: 0,
left: 0,
width: imageSize,
height: imageSize,
transform: [{ translateX: x.value }, { translateY: y.value }],
}));
return (
<View
style={{
flex: 1,
paddingTop: 100,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
}}
>
<ScrollView
horizontal={true}
showsHorizontalScrollIndicator={false}
style={{ positon: "relative", height: imageSize, borderWidth: 1 }}
contentContainerStyle={{ width: imageSize * 3 }}
>
<PanGestureHandler
ref={panRef}
simultaneousHandlers={longPressRef}
waitFor={longPressRef}
onHandlerStateChange={({ nativeEvent }) =>
console.log("PANGESTURE ", nativeEvent.state)
}
{...{ onGestureEvent }}
>
<Animated.View>
<LongPressGestureHandler
ref={longPressRef}
minDurationMs={1000}
simultaneousHandlers={panRef}
onHandlerStateChange={({ nativeEvent }) => {
console.log("LONG PRESS", nativeEvent.state);
console.log("LONG PRESS, PAN GESTURE SHOULD NOW ACTIVATE");
}}
>
<Animated.View
style={[
{
position: "absolute",
top: 0,
left: 0,
},
style,
]}
>
<Image
source={require("./assets/example.jpg")}
style={{ width: imageSize, height: imageSize }}
/>
</Animated.View>
</LongPressGestureHandler>
</Animated.View>
</PanGestureHandler>
</ScrollView>
</View>
);
}
Package versions
"expo": "~40.0.0",
"react-native-reanimated": "^2.0.0-rc.0",
"react-native-gesture-handler": "~1.8.0"
Issue Analytics
- State:
- Created 3 years ago
- Reactions:2
- Comments:14 (1 by maintainers)
Top GitHub Comments
For anyone coming across something like this in the future, this is how I solved it:
scrollEnabled
to your trigger value:onDragStart()
when you want to allow a component to be draggable. In the gestureHandler, filter on the trigger value from the previous step:scrollViewRef
to thePanGestureHandler
simultaneousHandlers prop.You can now enable and disable dragging your draggable component without having to lift your finger off the screen.
@MoOx hmm, damn it just doesn’t work for me. Once LongPressGestureHandler activates, then the PanGestureHandler deactivates and stops working. Somehow the PanGestureHandler also activates before LongPressGestureHandler (i.e. ignores waitFor). It is so weird…
This is the code I am using now, replicating what you just detailed out.