【问题标题】:PanResponder snaps Animated.View back to original position on second dragPanResponder 在第二次拖动时将 Animated.View 捕捉回原始位置
【发布时间】:2017-02-02 23:41:54
【问题描述】:

我创建了一个 PanResponder 来垂直移动 Animated.View。当我将它从原始位置移动时,它可以正常工作,但是一旦我第二次移动它,它就会弹回其原始位置,然后相对于触摸移动。

我将响应者直接解压到Animated.View,这是否会以某种方式导致这种行为?

我是这样定义 PanResponder 的:

this.state = {                            
  drag: new Animated.ValueXY()            
}                                         

this._responder = PanResponder.create({                                              
    onStartShouldSetPanResponder: () => true,                             
    onPanResponderMove: Animated.event([null, {                           
      dy: this.state.drag.y                                             
    }]),                                                                  
    onPanResponderRelease: (e, coords) => {
      ...
    }     
})

并将响应者应用到我的Animated.View

<Animated.View {...this._responder.panHandlers} style={this.state.drag.getLayout()}>
  // children go here
</Animated.View>                 

谢谢

【问题讨论】:

    标签: javascript reactjs react-native


    【解决方案1】:

    首先,让我们看看为什么会这样:

    • 您的 onPanResponderMove 回调读取手势的 dy(增量 Y),它为您提供自手势开始以来垂直移动的像素数量。这意味着每次您开始一个新手势时,增量都从 0 开始。

    • 另一方面,AnimatedXY#getLayout() 只是将y 值映射到样式属性top。这意味着当y 在触摸开始时设置为 0 时,元素将弹回其初始的非偏移位置。

    为了保留上一次拖动的偏移量,您可以使用setOffset 保留上一次偏移位置,然后setValue 将初始增量重置为 0。这可以在手势开始时完成,例如在onPanResponderGrant:

    this._responder = PanResponder.create({
      onStartShouldSetPanResponder: () => true,
      onPanResponderGrant: (evt, gestureState) => {
        this.state.drag.setOffset(this.state.drag.__getValue());
        this.state.drag.setValue({ x: 0, y: 0 });
      },
      onPanResponderMove: Animated.event([
        null,
        { dy: this.state. drag.y }
      ])
    });
    

    如您所见,我们在这里使用“私有”方法__getValue()。一般来说,不建议同步读取 Animated.value 的值,因为动画可能会被卸载到本机线程上,并且值可能不是最新的。在这里,在手势开始时,它应该是安全的。

    附带说明,由于您只是在 Y 轴上移动元素,因此您不一定需要使用二维 Animated.ValueXY,因为基本的 Animated.Value 就足够了。如果您重构代码以使用 Value,您只需调用 drag.extractOffset() 即可重置偏移量。它做同样的事情,但似乎在 AnimatedXY 上不可用。

    【讨论】:

    • 感谢您抽出宝贵时间回复这个很棒的答案并正确解释发生了什么。我最终使用与您提供的方法类似的方法解决了这个问题。
    【解决方案2】:

    你只需要调整onPanResponderGrant中的偏移量,就像

       onPanResponderGrant: (e, gestureState) => {
              this.state.drag.setOffset({x: this.state.drag.x._value, y: this.state.drag.y._value});
              this.state.drag.setValue({x: 0, y: 0})
    
          },
    

    但也要确保在panResponder释放时将偏移量变平,否则在第三次或第四次拖动时会出现一些故障(位置将根据之前的偏移量重置)。

      onPanResponderRelease: (e, {vx, vy}) => {
            this.state.drag.flattenOffset()      
       }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-30
      • 2014-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-24
      相关资源
      最近更新 更多