PanResponder 在第二次拖动时将 Animated.View 捕捉回原始位置 [英] PanResponder snaps Animated.View back to original position on second drag

查看:32
本文介绍了PanResponder 在第二次拖动时将 Animated.View 捕捉回原始位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have created a PanResponder to move a Animated.View vertically. When I move it from it's original position it works fine, but once I go to move it for a second time it snaps back to its original position and then moves relative to the touch.

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

I am unpacking the responder straight into the Animated.View, could this be causing this behaviour somehow?

以下是我定义 PanResponder 的方式:

Here is how I define my 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:

And applying the responder to my Animated.View:

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

谢谢

推荐答案

首先,让我们看看为什么会发生这种情况:

First, let's look at why this is happening:

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

  • Your onPanResponderMove callback reads the gesture's dy (delta Y), which gives you the amount of pixels moved vertically since the beginning of the gesture. This means that every time you start a new gesture, the delta starts from 0.

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

AnimatedXY#getLayout() on the other hand simply maps the y value to style property top. This means that when y is set to 0 in the beginning of the touch, the element will bounce back to its initial, non-offset position.

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

In order to preserve the offset from the previous drag, you can use setOffset to preserve the previous offset position, and then setValue to reset the initial delta to 0. This can be done when the gesture starts, e.g. on 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 的值,因为动画可能会被卸载到本机线程并且该值可能不是最新的.在这里,在手势开始时,它应该是安全的.

As you can see, we are using a "private" method __getValue() here. Generally, syncronously reading the value of an Animated.value is not recommended, because the animation may be offloaded onto the native thread and the value may not be up to date. Here, at the beginning of the gesture, it should be safe though.

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

As a side note, since you are only moving the element on the Y axis, you don't necessarily need to use the two-dimensional Animated.ValueXY, since a basic Animated.Value will suffice. If you refactor your code to use Value, you can just call drag.extractOffset() to reset the offset. It does the same thing, but does not appear to be available on AnimatedXY.

这篇关于PanResponder 在第二次拖动时将 Animated.View 捕捉回原始位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆