在 Animated.View 内反应 Native ScrollView 以制作类似 Bumble 的滑动系统
React Native ScrollView inside an Animated.View to make Bumble-like swipe system
我目前正在开发一个类似 Bumble 的滑动系统,这样我就可以水平滑动(多亏了 Animated.View 和 PanResponder,所以我可以随心所欲地移动视图)和垂直滑动(因为我的view 长于我的屏幕高度)。
经过一整天的搜索,我终于找到了一个解决方案,可以知道用户在 PanResponder 中是水平滚动还是垂直滚动,然后选择是否阻止移动
问题是我的 canMove() 函数的 console.log 每次都打印空值,所以目前只有我的垂直滚动条在工作。否则,当我在 onPanResponderMove 中打印我的 scrollType 值时,它的变化很好所以我不明白为什么我的 canMove() 函数得到 null
这是我的文件,您可以理解:
const story = useSelector((state) => state.entities.stories[storyId]);
const pan = useRef(new Animated.ValueXY(null, { useNativeDriver: true })).current;
const scrollType = useRef(null);
const checkSwipeDirection = (gestureState) => {
if (
(Math.abs(gestureState.dx) > Math.abs(gestureState.dy * 3))
&& (Math.abs(gestureState.vx) > Math.abs(gestureState.vy * 3))
) {
scrollType.current = 'horizontal';
} else {
scrollType.current = 'vertical';
}
};
const canMove = () => {
console.log('scrollType.current: ', scrollType.current);
if (scrollType.current === 'horizontal') {
return true;
}
return false;
};
const panResponder = useRef(
PanResponder.create({
onMoveShouldSetPanResponder: canMove,
onPanResponderGrant: () => {
pan.setValue({ x: 0, y: 0 });
},
onPanResponderMove: (evt, gestureState) => {
if (!scrollType.current) {
checkSwipeDirection(gestureState);
}
return Animated.event(
[null, { dx: pan.x, dy: pan.y }],
{ useNativeDriver: false },
);
},
onPanResponderRelease: () => {
Animated.spring(pan, {
toValue: 0,
useNativeDriver: false,
}).start();
scrollType.current = null;
},
}),
).current;
return (
<Animated.ScrollView
{...panResponder.panHandlers}
style={{
transform: [{ translateX: pan.x }, { translateY: pan.y },
{
rotate: pan.x.interpolate({
inputRange: [-200, 0, 200], outputRange: ['-20deg', '0deg', '20deg'],
}),
}],
}}
>
<TouchableOpacity activeOpacity={1} style={styles.card}>
<DiscoverCardHeader userId={story.recipient} />
<DiscoverStory
storyId={storyId}
navigation={navigation}
recipientId={story.recipient}
authorId={story.author}
/>
</TouchableOpacity>
</Animated.ScrollView>
);
};
如果您需要更多信息,我可以为您提供。希望我们能找到解决方案!谢谢
试试这个,新手 <3
const pan = useRef(new Animated.ValueXY(null, {useNativeDriver: true})).current;
var [direction, setDirection] = useState(0)
const panResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onPanResponderGrant: (evt, gestureState) => {
setDirection(0)
pan.setValue({x: 0, y: 0});
},
onPanResponderMove: (evt, gestureState) => {
if ((direction === 0 || direction === 1) &&
(gestureState.dy > 20 || gestureState.dy < -20)) {
setDirection(1)
pan.setValue({x: 0, y: 0});
} else if ((direction === 0 || direction === 2) &&
(gestureState.dx > 20 || gestureState.dx < -20)) {
setDirection(2)
pan.setValue({x: gestureState.dx, y: 0});
}
},
onPanResponderRelease: () => {
setDirection(0)
pan.setValue({x: 0, y: 0});
},
})
const translate = {
transform: [
...[pan.getTranslateTransform()[0]]
]
}
return (
<Animated.ScrollView scrollEnabled={direction !== 2} >
<Animated.View
{...panResponder.panHandlers}
style={[translate]}
>
<View style={{
backgroundColor: "red",
marginTop: 100
}}>
<View>
<Text> Coucou</Text>
<Text style={{
marginTop: 1000
}}> Coucou juyin le chien</Text>
</View>
</View>
</Animated.View>
</Animated.ScrollView>
);
我目前正在开发一个类似 Bumble 的滑动系统,这样我就可以水平滑动(多亏了 Animated.View 和 PanResponder,所以我可以随心所欲地移动视图)和垂直滑动(因为我的view 长于我的屏幕高度)。
经过一整天的搜索,我终于找到了一个解决方案,可以知道用户在 PanResponder 中是水平滚动还是垂直滚动,然后选择是否阻止移动
问题是我的 canMove() 函数的 console.log 每次都打印空值,所以目前只有我的垂直滚动条在工作。否则,当我在 onPanResponderMove 中打印我的 scrollType 值时,它的变化很好所以我不明白为什么我的 canMove() 函数得到 null
这是我的文件,您可以理解:
const story = useSelector((state) => state.entities.stories[storyId]);
const pan = useRef(new Animated.ValueXY(null, { useNativeDriver: true })).current;
const scrollType = useRef(null);
const checkSwipeDirection = (gestureState) => {
if (
(Math.abs(gestureState.dx) > Math.abs(gestureState.dy * 3))
&& (Math.abs(gestureState.vx) > Math.abs(gestureState.vy * 3))
) {
scrollType.current = 'horizontal';
} else {
scrollType.current = 'vertical';
}
};
const canMove = () => {
console.log('scrollType.current: ', scrollType.current);
if (scrollType.current === 'horizontal') {
return true;
}
return false;
};
const panResponder = useRef(
PanResponder.create({
onMoveShouldSetPanResponder: canMove,
onPanResponderGrant: () => {
pan.setValue({ x: 0, y: 0 });
},
onPanResponderMove: (evt, gestureState) => {
if (!scrollType.current) {
checkSwipeDirection(gestureState);
}
return Animated.event(
[null, { dx: pan.x, dy: pan.y }],
{ useNativeDriver: false },
);
},
onPanResponderRelease: () => {
Animated.spring(pan, {
toValue: 0,
useNativeDriver: false,
}).start();
scrollType.current = null;
},
}),
).current;
return (
<Animated.ScrollView
{...panResponder.panHandlers}
style={{
transform: [{ translateX: pan.x }, { translateY: pan.y },
{
rotate: pan.x.interpolate({
inputRange: [-200, 0, 200], outputRange: ['-20deg', '0deg', '20deg'],
}),
}],
}}
>
<TouchableOpacity activeOpacity={1} style={styles.card}>
<DiscoverCardHeader userId={story.recipient} />
<DiscoverStory
storyId={storyId}
navigation={navigation}
recipientId={story.recipient}
authorId={story.author}
/>
</TouchableOpacity>
</Animated.ScrollView>
);
};
如果您需要更多信息,我可以为您提供。希望我们能找到解决方案!谢谢
试试这个,新手 <3
const pan = useRef(new Animated.ValueXY(null, {useNativeDriver: true})).current;
var [direction, setDirection] = useState(0)
const panResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onPanResponderGrant: (evt, gestureState) => {
setDirection(0)
pan.setValue({x: 0, y: 0});
},
onPanResponderMove: (evt, gestureState) => {
if ((direction === 0 || direction === 1) &&
(gestureState.dy > 20 || gestureState.dy < -20)) {
setDirection(1)
pan.setValue({x: 0, y: 0});
} else if ((direction === 0 || direction === 2) &&
(gestureState.dx > 20 || gestureState.dx < -20)) {
setDirection(2)
pan.setValue({x: gestureState.dx, y: 0});
}
},
onPanResponderRelease: () => {
setDirection(0)
pan.setValue({x: 0, y: 0});
},
})
const translate = {
transform: [
...[pan.getTranslateTransform()[0]]
]
}
return (
<Animated.ScrollView scrollEnabled={direction !== 2} >
<Animated.View
{...panResponder.panHandlers}
style={[translate]}
>
<View style={{
backgroundColor: "red",
marginTop: 100
}}>
<View>
<Text> Coucou</Text>
<Text style={{
marginTop: 1000
}}> Coucou juyin le chien</Text>
</View>
</View>
</Animated.View>
</Animated.ScrollView>
);