【问题标题】:React Native: How to disable PanResponder temporarily?React Native:如何暂时禁用 PanResponder?
【发布时间】:2017-05-04 07:40:36
【问题描述】:

下面是创建panResponder实例的sn-p:

  constructor( props ) {
    super( props );

    this.position = new Animated.ValueXY();

    this.panResponder = PanResponder.create( {
      onStartShouldSetPanResponder: ( ) => true,
      onPanResponderMove: ( event, gesture ) => {
        this.position.setValue( { x: 0, y: gesture.dy } );
      },
      onPanResponderRelease: ( event, gesture ) => {
        if ( gesture.dy > SWIPE_THRESHOLD ) {
          this.forceSwipe( 'up' );
        } else if ( gesture.dy < -SWIPE_THRESHOLD ) {
          this.forceSwipe( 'down' );
        } else {
          this.resetPosition();
        }
      },
      onMoveShouldSetPanResponderCapture: ( evt, gestureState ) =>
      gestureState.dx !== 0 && gestureState.dy !== 0,
    } );
  }

  getCardStyle() {
    return {
      ...this.position.getLayout(),
    };
  }

下面是我的组件的代码sn-p:

<Animated.View
   key={ item.id }
   style={ [ this.getCardStyle(), styles.cardStyle ] }
   { ...this.panResponder.panHandlers }
>
  <Card
    shouldPanRespond={ this.shouldPanRespond }
     item={ item }
  />
</Animated.View>

卡片组件的代码sn-p:

  <TouchableOpacity
    activeOpacity={ 1 }
    style={ cardStyle }
    onPress={ this.onPress }
  >
    <ScrollView contentContainerStyle={ cardStyle }>
      <Image
        resizeMode="cover"
        style={ imageStyle }
        source={ { uri: img_url } }
      />

      <View style={ titleWrapStyle }>
        <Text style={ textStyle }>{ title }</Text>
      </View>
    </ScrollView>
  </TouchableOpacity>

我正在构建绝对排在另一张之后的卡片。然后可以使用panResponder 向上或向下滑动这些卡片。但是,在点击屏幕时,我应该在同一屏幕上显示详细信息页面。

现在,我可以检测到点击,但是每当用户点击/点击时,我想禁用panResponder,以便无法刷卡并且用户可以滚动浏览内容。一旦用户滚动到最后,我想重新启用滑动,即我想启用平移。

我知道onStartShouldSetResponder: () =&gt; false 会禁用panResponder,但我们如何在创建实例后禁用它。我在其他地方找不到太多关于它的信息。

【问题讨论】:

    标签: javascript android ios reactjs react-native


    【解决方案1】:

    对于将要寻找如何暂时禁用 PanResponder 的人,以下是我的解决方案。

    就像@RaHuL - House Javascript 注意到的那样,另一个答案并没有真正解决问题,因为将onStartShouldSetResponder 设置为与某个可能从 true 变为 false 的状态值相对应的值不会影响 PanResponder(至少看起来所以)如果它是用true创建的。

    我通过更改onPanResponderMove 函数解决了类似的问题。我在状态中有一个值:panResponderEnabled,我的函数如下所示:

     onPanResponderMove: ( event, gesture ) => {
        if(this.state.panResponderEnabled){
           this.position.setValue( { x: 0, y: gesture.dy } ); 
        }
    }
    

    当我不想从 PanRespoder 读取更改时,我只需将 panResponderEnabled 设置为 false。

    【讨论】:

      【解决方案2】:

      我想我找到了一种使用 onStartShouldSetResponder 临时禁用 PanResponder 的方法。目标是在真假之间切换,即使它似乎没有响应状态值的变化。如果您使用的是功能组件,那么钩子useRef 似乎可以解决问题。

      const [panResponderEnabled, _setPanResponderEnabled] = useState(true)
      
      const panResponderEnabledRef = useRef(panResponderEnabled)
      const setPanResponderEnabled = data => {
        panResponderEnabledRef.current = data
        _setPanResponderEnabled(data)
      }
      

      然后当你创建你的 PanResponder 时:

      onStartShouldSetPanResponder: () => panResponderEnabledRef.current,
      

      【讨论】:

        【解决方案3】:

        如果您想要一个非常简单的蛮力解决方案,请在动画视图上使用 pointerEvents 道具。

        pointerEvents={stopPan ? 'none' : 'auto'}

        stopPan 为真时,这将停止视图及其下方的所有触摸事件。

        【讨论】:

          【解决方案4】:

          代替onStartShouldSetResponder 的箭头函数,您可以使用类函数并使用状态来返回真/假。像这样的

           constructor( props ) {
              super( props );
              this.state = {
                panResponderEnabled: true
              }
              this.position = new Animated.ValueXY();
          
              this.panResponder = PanResponder.create( {
                onStartShouldSetPanResponder: ( ) => true,
                onPanResponderMove: ( event, gesture ) => {
                  this.position.setValue( { x: 0, y: gesture.dy } );
                },
                onPanResponderRelease: ( event, gesture ) => {
                  if ( gesture.dy > SWIPE_THRESHOLD ) {
                    this.forceSwipe( 'up' );
                  } else if ( gesture.dy < -SWIPE_THRESHOLD ) {
                    this.forceSwipe( 'down' );
                  } else {
                    this.resetPosition();
                  }
                },
                onMoveShouldSetPanResponderCapture: ( evt, gestureState ) =>
                gestureState.dx !== 0 && gestureState.dy !== 0,
              } );
            }
          
            handlePanResponderStart = () => {
              return this.state.panResponderEnabled;
            }
            onCardPress = () => {
              this.setState({
                panResponderEnabled: false
              });
            }
            getCardStyle() {
              return {
                ...this.position.getLayout(),
              };
            }
          

          【讨论】:

          • 我试过了。我将 this.handlePanResponderStart 分配给 onStartShouldSetResponder 您在答案中错过了。没用。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-02
          • 2018-02-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多