Home > OS >  react-native-gesture-handler not recognize double tap
react-native-gesture-handler not recognize double tap

Time:07-20

I followed to the newest RNGH docs

I can't get the double tap event to work, seems like RNGH only recognize the event with less tap (I changed the numberOfTaps of const singleTap to 3 and the doubleTap worked)

I tried to change the order of Exclusive (not working)

Using old RNGH 1.10.3 like this video

https://www.youtube.com/watch?v=nbEmo0zLJjw&list=PLjHsmVtnAr9TWoMAh-3QMiP7bPUqPFuFZ&index=6

But none of these methods are worked

Gesture:

  const singleTap = Gesture.Tap().onEnd((_event, success) => {
    if (success) {
      console.log("single tap!");
    }
  });
  const doubleTap = Gesture.Tap()
    .numberOfTaps(2)
    .onEnd((_event, success) => {
      if (success) {
        console.log("double tap!");
      }
    });

  const taps = Gesture.Exclusive(doubleTap, singleTap);

Component:

    <View style={styles.container}>
      <GestureDetector gesture={taps}>
        <Animated.View>
          <ImageBackground
            source={require("./assets/image.jpg")}
            style={styles.image}
          >
            <Image
              source={require("./assets/heart.png")}
              style={[
                styles.image,
                {
                  shadowOffset: { width: 0, height: 20 },
                  shadowOpacity: 0.35,
                  shadowRadius: 35,
                },
              ]}
              resizeMode={"center"}
            />
          </ImageBackground>
        </Animated.View>
      </GestureDetector>
    </View>

CodePudding user response:

I have also tried and failed with your example and several others, e.g.

I am using Expo, but I do not know if it has anything to do with it. If none of these are working for you, then try my manual implementation of the functionality as a last resort:

import React, { useCallback, useState } from "react";
import { Pressable, StyleSheet } from "react-native";

interface DoubleTapWrapperProps {
  delay?: number;
  children: React.ReactNode;
  onSingleTap: () => void;
  onDoubleTap: () => void;
}

export default function DoubleTapWrapper({
  delay = 300,
  children,
  onSingleTap,
  onDoubleTap,
}: DoubleTapWrapperProps) {
  const [firstPress, setFirstPress] = useState(true);
  const [lastTime, setLastTime] = useState(new Date().getTime());
  const [timer, setTimer] = useState<NodeJS.Timeout | null>(null);

  const onTap = useCallback(() => {
    let now = new Date().getTime();

    // Single tap
    if (firstPress) {
      setFirstPress(false);

      setTimer(
        setTimeout(() => {
          onSingleTap && onSingleTap();

          setFirstPress(true);
          setTimer(null);
        }, delay)
      );

      setLastTime(now);
    } else {
      // Double tap
      if (now - lastTime < delay) {
        timer && clearTimeout(timer);
        onDoubleTap && onDoubleTap();
        setFirstPress(true);
      }
    }
  }, [firstPress, lastTime, delay, onDoubleTap, onSingleTap, timer]);

  return (
    <Pressable onPress={onTap} style={styles.container}>
      {children}
    </Pressable>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});

This is a functional component based on an implementation found here. Example of usage:

export default function Example() {
  return (
    <DoubleTapWrapper
      onSingleTap={() => {
        console.log("single");
      }}
      onDoubleTap={() => {
        console.log("double");
      }}
    >
      <View style={styles.container}>
        <Text style={styles.title}>Double tap example</Text>
      </View>
    </DoubleTapWrapper>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
  },
  title: {
    fontSize: 20,
    fontWeight: "bold",
  },
  separator: {
    marginVertical: 30,
    height: 1,
    width: "80%",
  },
});

CodePudding user response:

Supposedly this is an expo issue that is only affecting expo on IOS. Expo will hopefully resolve soon in a later version. I am in the same boat as you and will most likely implement the above solution for now.

  • Related