使用React Native Gesture Handler和Reanimated检测滑动方向

3
我们已经开发了一个使用React Native PanResponder的swiper(在有人评论之前)-我们不能在这里使用任何其他swiper库。 在我们开发的swiper中,当用户结束滑动(即释放Pan)时,启动弹簧动画时会出现延迟的问题。
因此,为了解决这个问题,我们正在尝试从 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中检测pan移动方向是非常容易的。

这里出现了Gesture Handler的问题,

当手势状态处于活动状态时,我无法检测到swipe。

我已经在Gesture Handler中搜索了问题,并找到了this

该问题中提出了两个解决方法。

  1. 第一个是由Sonaye提供的,它有两个处理程序并在两个处理程序的onHandlerStateChange中检测滑动方向,但在使用重新动画时并不实用,因为它仅在处理程序状态更改时设置滑动方向。
  2. 第二个是由Satya提供的,它实际上在状态为ACTIVE时检测滑动,但他使用了translationX属性,该属性对我们也可以是负的,并且可以像swiper一样向任何方向移动。

这两种解决方法都无法解决我们的问题。

那么,是否有其他方法可以使用PanGestureHandler和Reanimated找到方向?我尝试使用PanResponder和Reanimated与dx值一起使用,但最终出现了错误消息,即nativeEvent属性仅支持作为来自PanResponder的gestureState参数的dx

注意:我们无法在Fling的onHandlerStateChange中使用FlingGestureHandlerSwipeables,因为我们需要找到方向,而Swipeables不使用Reanimated。
4个回答

7

您可以通过属性 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>
);



0
对于那些想要使用双 FlingGestureHandler 来实现垂直或水平滑动手势的人,这里提供了解决方案:
首先,您必须为所需的方向初始化 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,
        },
      );
    }
  };

然后你需要将这些处理程序绑定到RNGH的2个FlingGestureHandler组件

<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>

-1
请使用translationX属性而不是nativeEvent的velocityX属性:

 const handleGesture = (evt) => {
    const { nativeEvent } = evt;
    if (nativeEvent.translationX > 0) {
      Alert.alert('Swipe right');
    } else {
      Alert.alert('Swipe left');
    }
  };


-2
在我的情况下,我使用了双重 FlingGestureHandler 来检测方向。这对我很有效。

双重FlingGestureHandlers - v.Vinh
4
请注意,您始终可以 [编辑] 您的答案。因此,无需使用评论来更新您的答案。 - fcdt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接