我的手势在Android设备上有问题。
我的Animated.View内部有一个Animated.ScrollView。每当我缓慢拖动Animated.View时,它都能正常工作,但是只要我快速滑动一下,Animated.View就会在几个像素后停止。
当我禁用Animated.ScrollView上的滚动时,该错误不会发生。我的猜测是,如果滑动速度过快,则Animated.ScrollView会接手。
任何人都知道为什么会这样吗?在iOS上不会发生这种情况。
详细信息视图:
class DetailScreen extends PureComponent<Props> {
state = {
closeToTop: true,
closeToBottom: false
};
scrollY = new Animated.Value(0);
scrollView?: ScrollView;
handleScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
const closeToTop = this.isCloseToTop(e);
if (closeToTop !== this.state.closeToTop) {
this.setState({ closeToTop });
}
const closeToBottom = this.isCloseToBottom(e);
if (closeToBottom !== this.state.closeToBottom) {
this.setState({ closeToBottom });
}
};
isCloseToTop = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
const { contentOffset } = e.nativeEvent;
return contentOffset.y === 0;
};
isCloseToBottom = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
const { layoutMeasurement, contentOffset, contentSize } = e.nativeEvent;
return layoutMeasurement.height + contentOffset.y >= contentSize.height - 20;
};
renderContent = () => {
return (
<Animated.ScrollView
contentContainerStyle={{ flexGrow: 1 }}
scrollEventThrottle={16}
bounces={false}
// scrollEnabled={false}
overScrollMode={"never"}
onScroll={Animated.event(
[
{
nativeEvent: {
contentOffset: {
y: this.scrollY
}
}
}
],
{
useNativeDriver: true,
listener: this.handleScroll
}
)}
ref={(ref: any) => (this.scrollView = ref && ref.getNode())}>
<TouchableWithoutFeedback>
<View style={{flex: 1}}>
<View style={{...styles.container, height: 200, backgroundColor: "red"}}>
<Text>red</Text>
</View>
<View style={{ ...styles.container, height: 200, backgroundColor: "yellow" }}>
<Text>yellow</Text>
</View>
<View style={{ ...styles.container, height: 200, backgroundColor: "green" }}>
<Text>green</Text>
</View>
<View style={{ ...styles.container, height: 200, backgroundColor: "blue" }}>
<Text>blue</Text>
</View>
<View style={{ ...styles.container, height: 200, backgroundColor: "red" }}>
<Text>red</Text>
</View>
<View style={{ ...styles.container, height: 200, backgroundColor: "yellow" }}>
<Text>yellow</Text>
</View>
</View>
</TouchableWithoutFeedback>
</Animated.ScrollView>
);
};
render() {
return (
<SwipeableModal
onClose={this.props.navigation.pop}
nearTop={this.state.closeToTop}
nearBottom={this.state.closeToBottom}>
{this.renderContent()}
</SwipeableModal>
);
}
}
可滑动模式
const { height: screenHeight } = Dimensions.get("window");
const TIMING_CONFIG = { duration: 300, easing: Easing.inOut(Easing.ease) };
class SwipeableModal extends PureComponent<Props, State> {
panResponder: PanResponderInstance;
constructor(props: Props) {
super(props);
this.state = {
pan: new Animated.ValueXY({ x: 0, y: 0 }),
isDragging: false
};
this.panResponder = PanResponder.create({
// Ask to be the responder:
onStartShouldSetPanResponder: () => false,
onStartShouldSetPanResponderCapture: () => false,
onMoveShouldSetPanResponderCapture: () => false,
onPanResponderTerminationRequest: () => false,
onMoveShouldSetPanResponder: (evt, gestureState) => {
if (this.state.isDragging) {
return true;
}
// moving finger from top to bottom
if (gestureState.vy > 0 && this.props.nearTop) {
this.setState({ isDragging: true });
return true;
}
// moving finger from bottom to top
if (gestureState.vy < 0 && this.props.nearBottom) {
this.setState({ isDragging: true });
return true;
}
return false;
},
onPanResponderMove: (evt, gestureState) => {
this.state.pan.setValue({ x: 0, y: gestureState.dy });
},
onPanResponderRelease: (evt, gestureState) => {
this.setState({ isDragging: false });
if (gestureState.vy <= -0.7 || gestureState.dy <= -300) {
// move from bottom to top
Animated.timing(this.state.pan, {
toValue: { x: 0, y: -screenHeight },
...TIMING_CONFIG
}).start(this.closeModal);
} else if (gestureState.vy >= 0.5 || gestureState.dy >= 300) {
// move from top to
Animated.timing(this.state.pan, {
toValue: { x: 0, y: screenHeight },
...TIMING_CONFIG
}).start(this.closeModal);
} else {
Animated.spring(this.state.pan, {
toValue: 0
}).start();
}
}
});
}
closeModal = () => {
this.props.onClose();
};
handleGetStyle() {
return [
style.container,
{
transform: [...this.state.pan.getTranslateTransform()]
}
];
}
render() {
return (
<Animated.View style={this.handleGetStyle()} {...this.panResponder.panHandlers}>
{this.props.children}
</Animated.View>
);
}
}
答案 0 :(得分:0)
对于那些想知道的人,我能够通过使用react-native-gesture-handler重新实现可滑动模式来解决此问题。
如果有人需要帮助,请告诉我。