![](/img/trans.png)
[英]PanResponder not working properly on Android when Animated.View has an Animated.ScrollView as a child
[英]PanResponder snaps Animated.View back to original position on second drag
我创建了一个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开始。
另一方面, 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
上可用。
你只需要在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()
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.