I am trying to add a Scrollview to my card in react native. However my card is animated and if I try to scroll I think it assumes it for swiping up instead. Alongside this the way my card is set out currently has turned the card into one long card rather than a set size card that can be scrolled.
Here is what my card looks like:
Although it doesnt show it well, the card has just elongated rather than kept the same size and added a scrolling option.The code for my card is:
const Card = ({ name, source, isFirst, swipe, tiltSign, ...rest }: props) => {const rotate = Animated.multiply(swipe.x, tiltSign).interpolate({ inputRange: [-ACTION_OFFSET, 0, ACTION_OFFSET], outputRange: ['8deg', '0deg', '-8deg'],});const likeOpacity = swipe.x.interpolate({ inputRange: [25, ACTION_OFFSET], outputRange: [0, 1], extrapolate: 'clamp',});const nopeOpacity = swipe.x.interpolate({ inputRange: [-ACTION_OFFSET, -25], outputRange: [1, 0], extrapolate: 'clamp',});const animatedCardStyle = { transform: [...swipe.getTranslateTransform(), {rotate}],};const renderChoice = useCallback(() => { return (<><Animated.View style={[ styles.choiceContainer, styles.likeContainer, {opacity: likeOpacity}, ]}><Choice type="like"/></Animated.View><Animated.View style={[ styles.choiceContainer, styles.nopeContainer, {opacity: nopeOpacity}, ]}><Choice type="nope"/></Animated.View></> );}, [likeOpacity, nopeOpacity]);return (<Animated.ScrollView style={[styles.container, isFirst && animatedCardStyle]} {...rest}><Image source={source} style={styles.image}/><Text style={styles.name}>{name}</Text><Text>Hello</Text><Image source={source} style={styles.image}/><Image source={source} style={styles.image}/><Image source={source} style={styles.image}/><LinearGradient colors={['transparent', 'rgba(0,0,0,0.9)']} style={styles.gradient} /> {isFirst && renderChoice()}</Animated.ScrollView>);
I feel the styling of it may also help:
container: { position: 'absolute', top: 45,},image: { width: CARD.WIDTH, height: CARD.HEIGHT, borderRadius: CARD.BORDER_RADIUS,},gradient: { position: 'absolute', bottom: 0, left: 0, right: 0, height: 160, borderRadius: CARD.BORDER_RADIUS,},name: { position: 'absolute', bottom: 22, left: 22, fontSize: 36, fontWeight: 'bold', color: '#fff',},choiceContainer: { position: 'absolute', top: 100,},likeContainer: { left: 45, transform: [{ rotate: '-30deg' }],},nopeContainer: { right: 45, transform: [{ rotate: '30deg' }],},
Here is also my swiping screen which the card is used in:
import React, { useCallback, useEffect, useRef, useState } from 'react';import { Animated, PanResponder, View } from 'react-native';import Card from '../card/Card';import { ACTION_OFFSET, CARD } from '../../utils/constants';import { pets as petsArray } from './data';import {styles} from "./styles";const Swipe = () => { const [pets, setPets] = useState(petsArray); const swipe = useRef(new Animated.ValueXY()).current; const tiltSign = useRef(new Animated.Value(1)).current; useEffect(() => { if (!pets.length) { setPets(petsArray); } }, [pets.length]); const panResponder = PanResponder.create({ onMoveShouldSetPanResponder: () => true, onPanResponderMove: (_, { dx, dy, y0 }) => { swipe.setValue({ x: dx, y: dy }); tiltSign.setValue(y0 > CARD.HEIGHT / 2 ? 1 : -1); }, onPanResponderRelease: (_, { dx, dy }) => { const direction = Math.sign(dx); const isActionActive = Math.abs(dx) > ACTION_OFFSET; if (isActionActive) { Animated.timing(swipe, { duration: 200, toValue: { x: direction * CARD.OUT_OF_SCREEN, y: dy, }, useNativeDriver: true, }).start(removeTopCard); } else { Animated.spring(swipe, { toValue: { x: 0, y: 0, }, useNativeDriver: true, friction: 5, }).start(); } }, }); const removeTopCard = useCallback(() => { setPets((prevState) => prevState.slice(1)); swipe.setValue({ x: 0, y: 0 }); }, [swipe]); const handleChoice = useCallback( (direction) => { Animated.timing(swipe.x, { toValue: direction * CARD.OUT_OF_SCREEN, duration: 400, useNativeDriver: true, }).start(removeTopCard); }, [removeTopCard, swipe.x] ); return (<View style={styles.container}> {pets .map(({ name, source }: any, index: number) => { const isFirst = index === 0; const dragHandlers = isFirst ? panResponder.panHandlers : {}; return (<Card key={name} name={name} source={source} isFirst={isFirst} swipe={swipe} tiltSign={tiltSign} {...dragHandlers} /> ); }) .reverse()}</View> );};export default Swipe;
Any help as to how to just make the card scroll rather than what it is currently would be great! Thanks!