Определите направление смахивания с помощью React Native Gesture Handler и Reanimated

Мы уже разработали swiper с использованием React Native PanResponder (до того, как кто-то прокомментирует) - мы не можем использовать здесь никакую другую библиотеку swiper. В разработанном нами свайпере мы сталкиваемся с проблемой, когда пользователь завершает свайп (то есть отпускает панорамирование), возникает задержка при запуске весенней анимации.

Поэтому, чтобы исправить это, мы пытаемся перейти от React Native Animated API к Reanimated Libary, что могло бы решить проблему лагов, с которыми сталкивается пользователь.

Но при разработке с помощью React Native Gesture Handler (PanGestureHandler) и Reanimated Library мы не можем определить направление смахивания в обработчике жестов.

Я добавляю часть кода, которую мы использовали для определения направления смахивания в PanResponder.

onPanMoving = (evt, {dx}) => {
   this.draggedEnd = dx < -this.swipeThreshold; //You are moving towards right screen
   this.draggedStart = dx > this.swipeThreshold; //You are moving towards left screen
}

Как видите, определить направление при движении панорамирования в PanResponder было очень просто.

Вот проблема с Gesture Handler,

Я не могу обнаружить смахивание при активном состоянии жеста

Я уже искал проблемы в Gesture Handler и нашел это.

В этой проблеме было предложено два обходных пути

  1. Первый - от Sonaye, который имеет два обработчика и определяет направление смахивания в onHandlerStateChange для обоих обработчиков, что не помогло при использовании reanimated, поскольку оно устанавливает направление смахивания только при изменении состояния обработчиков.
  2. Второй один является Satya, который на самом деле обнаруживает красть, когда государство является активным, но он использует translationX свойство, свойство translationX может также негативно для нас и может двигаться в любом направлении, совпадающем с Swiper.

Оба пути не решают нашу проблему.

Есть ли другой способ найти направление с помощью PanGestureHandler и Reanimated. Я попытался использовать PanResponder с Reanimated со значением dx, но в итоге появилось сообщение об ошибке, т.е. свойства nativeEvent поддерживаются только потому, что dx взят из параметра gestureState из PanResponder.

Примечание. Мы не можем использовать FlingGestureHandler и Swipeables, потому что нам нужно найти направление в Fling по-прежнему onHandlerStateChange, а Swipeables не использует Reanimated.

4 ответа

Вы можете определить направление, проведя по горизонтали через свойство velocityX

Пример :

      const handleGesture = (evt) => {
    const { nativeEvent } = evt;

    if (nativeEvent.velocityX > 0) {
      console.log('Swipe right');
    } else {
      console.log('Swipe left');
    }
  };

return (
   <PanGestureHandler onGestureEvent={handleGesture}>
       // child component
   </PanGestureHandler>
);


Для тех, кто хочет использовать двойной жест вертикального или горизонтального броска, вот решение:

Сначала вы должны инициализировать stateHandlersдля нужного вам направления. В моем случае я пытался реализовать вертикальный flingGestureHandler.

        const onDownFlingHandlerStateChange = ({
    nativeEvent,
  }: FlingGestureHandlerStateChangeEvent) => {
    if (nativeEvent.oldState === State.ACTIVE) {
      progressHeight.value = withTiming(COLLAPSED_HEIGHT, {
        duration: ANIMATION_DURATION,
      });
    }
  };

  const onUpFlingHandlerStateChange = ({
    nativeEvent,
  }: FlingGestureHandlerStateChangeEvent) => {
    if (nativeEvent.oldState === State.ACTIVE) {
      progressHeight.value = withTiming(
        DEVICE_HEIGHT - TOP_PADDING_FOR_EXPANDED,
        {
          duration: ANIMATION_DURATION,
        },
      );
    }
  };

а затем вам нужно привязать эти обработчики к 2 FlingGestureHandlerкомпонент RNGH

      <FlingGestureHandler
  onHandlerStateChange={onUpFlingHandlerStateChange}
  onEnded={() => {
     onPressChecklistIcon();
  }}
  direction={Directions.UP}>
  <FlingGestureHandler
    direction={Directions.DOWN}
    onEnded={() => {
      onPressChecklistIcon();
    }}
    onHandlerStateChange={onDownFlingHandlerStateChange}>
    <Animated.View style={[styles.container, reanimatedStyle]}>
      <View style={styles.closerContainer}>
        <View style={styles.closer} />
      </View>
      {renderChecklistContent()}
    </Animated.View>
  </FlingGestureHandler>
</FlingGestureHandler>

Используйте свойство translationX, а не свойство Velocity для nativeEvent:

В моем случае я использовал для определения направления. У меня это сработало.

Другие вопросы по тегам