我创建了一个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>
谢谢
答案 0 :(得分:8)
首先,让我们来看看为什么会这样:
您的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
上似乎没有。
答案 1 :(得分: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时平移偏移量,否则当你拖动第3次或第4次时它会有一些毛刺(位置将根据先前的偏移重置)。
onPanResponderRelease: (e, {vx, vy}) => {
this.state.drag.flattenOffset()
}