I’m currently working on a Bumble-like swipe system so I can swipe horizontally (thanks to an Animated.View and a PanResponder so I can move my view wherever I want), and vertically (because my view is longer than the height of my screen).
After a long day of search, I finally found a solution which permits to know if the user is scrolling horizontally or vertically in the PanResponder, then choose if i block the move or not
The problem is that my canMove() function’s console.log is printing null every time so only my vertical scroll is working currently. Otherwise, when i print my scrollType value in the onPanResponderMove, it changes well so I don’t understand why my canMove() function gets null
here’s my file so you can understand:
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> ); };
if you need more informations i’m there to give you. hope we’ll find a solution ! thanks
Advertisement
Answer
Try this, newbies <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> );