我创建了一个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>
感谢
首先,让我们看看为什么会发生这种情况:
-
您的
onPanResponderMove
回调读取手势的dy
(delta Y),它为您提供自手势开始以来垂直移动的像素量。这意味着,每次你开始一个新的手势时,delta都会从0开始。 -
CCD_ 6简单地将CCD_ 7值映射到样式属性CCD_。这意味着,当
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
上不可用。
您只需要调整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()
}