我也曾经为这个问题苦恼了几天。据我所知,这个问题不仅限于材料顶部选项卡或页面视图。如果您将水平滚动视图或平面列表放入垂直滚动视图中,则父垂直滚动视图有时会窃取水平手势。
我注意到水平滚动视图上调用了onResponderTerminate回调。React Native提供了一种通过传递onResponderTerminationRequest={(event) => false}属性来防止终止的方法,但似乎没有任何作用。终止回调仍然被调用。第一个这方面的错误报告已经有6年之久,我也没有找到任何可行的解决方法。
一个临时的解决方法是使用react-native-gesture-handler和react-native-reanimated构建自己的滚动视图。下面是如何制作一个完整示例。请注意,必须从react-native-reanimated导入Animated。如果需要使用来自react-native的Animated,请使用别名导入 --> import {Animated as Anim} from 'react-native';
import React from 'react';
import { Animated as Anim, ScrollView, Text, View } from 'react-native';
import Animated, {
useAnimatedStyle,
useSharedValue,
withDecay,
withSpring
} from "react-native-reanimated";
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
export const MyTab = () => {
const SCROLLABLE_WIDTH = 200;
const animatedX = useSharedValue(0);
const xContext = useSharedValue(0);
const animStyle = useAnimatedStyle(() => {
return {
transform: [{ translateX: animatedX.value }]
}
})
const panGesture = React.useMemo(() => Gesture.Pan()
.activeOffsetX([-17, 17])
.activeOffsetY([-22, 22])
.maxPointers(1)
.onStart((e) => {
xContext.value = animatedX.value;
})
.onUpdate((e) => {
const target = xContext.value + e.translationX;
if (target > 0) {
animatedX.value = target * 0.3;
}
else if (target < -SCROLLABLE_WIDTH) {
animatedX.value = -SCROLLABLE_WIDTH + (SCROLLABLE_WIDTH + target) * 0.3;
}
else {
animatedX.value = target;
}
})
.onEnd((e) => {
const target = xContext.value + e.translationX;
if (target > 0) {
animatedX.value = withSpring(0, { mass: 0.3, stiffness: 110 });
}
else if (target < -SCROLLABLE_WIDTH) {
animatedX.value = withSpring(-SCROLLABLE_WIDTH, { mass: 0.3, stiffness: 110 });
}
else {
animatedX.value = withDecay({
velocity: e.velocityX,
clamp: [-SCROLLABLE_WIDTH, 0],
});
}
}),
[]
);
return (
<ScrollView style={{}}>
<GestureDetector
gesture={panGesture}
>
{/* If no static container is set, a tab change might initialize
If you need to hide overflow set overflow: "hidden" to the container style */}
<Animated.View style={{ marginVertical: 50 }}>
<Animated.View
style={[{
flexDirection: "row"
},
animStyle
]}>
<Text style={{ color: "#abcdef", fontSize: 28, marginHorizontal: 20 }}>
{"Horizontally\nscrollable\nitem 1"}
</Text>
<Text style={{ color: "#abcdef", fontSize: 28, marginHorizontal: 20 }}>
{"Horizontally\nscrollable\nitem 2"}
</Text>
<Text style={{ color: "#abcdef", fontSize: 28, marginHorizontal: 20 }}>
{"Horizontally\nscrollable\nitem 3"}
</Text>
<Text style={{ color: "#abcdef", fontSize: 28, marginHorizontal: 20 }}>
{"Horizontally\nscrollable\nitem 4"}
</Text>
</Animated.View>
</Animated.View>
</GestureDetector>
</ScrollView>
)
}
horizontal={true}
属性吗?还是你真的是指onScroll
函数? - Christian Aichnerreact-native-gesture-handler
。然而,只能在Android上解决。 - Annie Tan