简体   繁体   English

如何使用功能 react-native 从 PanResponder 中删除第一张卡?

[英]How to remove the first card from PanResponder by using functional react-native?

I'm learning the react-native and yes I'm beginner, I want to make similar like Tinder apps, but I have met a problem which is cannot swipe the first card(mean cannot remove the first card).我正在学习 react-native 是的,我是初学者,我想制作类似 Tinder 应用程序,但我遇到了一个问题,即无法刷第一张卡(意味着无法移除第一张卡)。 There has no error message for these codes.这些代码没有错误消息。 I have tried few of solutions but still cannot work too.我尝试了一些解决方案,但仍然无法工作。 Please somebody help me for these codes.请有人帮助我获取这些代码。

import React, { useEffect,useState,useRef } from 'react';
import { StyleSheet, Text, View, Dimensions, Image, Animated, PanResponder, Platform } from 'react-native';

const SCREEN_HEIGHT = Dimensions.get('window').height;
const SCREEN_WIDTH = Dimensions.get('window').width;
import Icon from 'react-native-vector-icons/Ionicons';
const Users = [
  { id: "1", uri: require('../image/antman.jpg') },
  { id: "2", uri: require('../image/butterfly.jpg') },
  { id: "3", uri: require('../image/captainmarvel.jpg') },
  { id: "4", uri: require('../image/antman.jpg') },
  { id: "5", uri: require('../image/antman.jpg') },
]

const colors = [
  {
    id: 1,
    color: 'red',
  },
  {
    id: 2,
    color: 'green'
  },
  {
    id: 3,
    color: 'blue',
  }
]

const SignUpScreen = () =>{

    const [position, setPosition] = useState(new Animated.ValueXY());
    const [currentIndex,setCurrentIndex] =useState(0);

    const rotate = position.x.interpolate({
      inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
      outputRange: ['-30deg', '0deg', '10deg'],
      extrapolate: 'clamp'
    })

    const rotateAndTranslate = {
      transform: [{
        rotate: rotate
      },
      ...position.getTranslateTransform()
      ]
    }

    const likeOpacity = position.x.interpolate({
      inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
      outputRange: [0, 0, 1],
      extrapolate: 'clamp'
    })
    const dislikeOpacity = position.x.interpolate({
      inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
      outputRange: [1, 0, 0],
      extrapolate: 'clamp'
    })

    const nextCardOpacity = position.x.interpolate({
      inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
      outputRange: [1, 0, 1],
      extrapolate: 'clamp'
    })
    const nextCardScale = position.x.interpolate({
      inputRange: [-SCREEN_WIDTH / 2, 0, SCREEN_WIDTH / 2],
      outputRange: [1, 0.8, 1],
      extrapolate: 'clamp'
    })


 
    const panResponder = PanResponder.create({

      onStartShouldSetPanResponder: (evt, gestureState) => true,
      onPanResponderMove: (evt, gestureState) => {

        setPosition(new Animated.ValueXY({x: gestureState.dx, y: gestureState.dy}));
      },
      onPanResponderRelease: (evt, gestureState) => {

        if (gestureState.dx > 120) {
          Animated.spring(position, {
            toValue: { x: SCREEN_WIDTH + 100, y: gestureState.dy }//,
            //duration: 500
          }).start(() => {
            //setCurrentIndex(currentIndex + 1 ), 
            setPosition(new AnimatedValue({x: 0, y: 0 }));  
            })
          }
        else if (gestureState.dx < -120) {
          Animated.spring(position, {
            toValue: { x: -SCREEN_WIDTH - 100, y: gestureState.dy }//,
            //duration: 500
          }).start(() => {
            //setCurrentIndex(currentIndex + 1 ), 
            setPosition(new AnimatedValue({x: 0, y: 0 }));  
            })
        }
        else {
          Animated.spring(position, {
            toValue: { x: 0, y: 0 },
            duration: 500
            //friction: 4
          }).start()
        }
      }
    })
  


  renderUsers = () => {

    return Users.map((item, i) => {

      
      if (i < currentIndex) {
        return null;
      }
      else if (i == currentIndex) {

        return (
          <Animated.View
            {...panResponder.panHandlers}
            key={item.id} style={[rotateAndTranslate, { height: SCREEN_HEIGHT - 120, width: SCREEN_WIDTH, padding: 10, position: 'absolute' }]}>
            <Animated.View style={{ opacity: likeOpacity, transform: [{ rotate: '-30deg' }], position: 'absolute', top: 50, left: 40, zIndex: 1000 }}>
              <Text style={{ borderWidth: 1, borderColor: 'green', color: 'green', fontSize: 32, fontWeight: '800', padding: 10 }}>LIKE</Text>

            </Animated.View>

            <Animated.View style={{ opacity: dislikeOpacity, transform: [{ rotate: '30deg' }], position: 'absolute', top: 50, right: 40, zIndex: 1000 }}>
              <Text style={{ borderWidth: 1, borderColor: 'red', color: 'red', fontSize: 32, fontWeight: '800', padding: 10 }}>NOPE</Text>

            </Animated.View>

            <Image
              style={{ flex: 1, height: null, width: null, resizeMode: 'cover', borderRadius: 20 }}
              source={item.uri} />

          </Animated.View>
        )
      }
      else {
        return (
          <Animated.View

            key={item.id} style={[{
              opacity: nextCardOpacity,
              transform: [{ scale: nextCardScale }],
              height: SCREEN_HEIGHT - 120, width: SCREEN_WIDTH, padding: 10, position: 'absolute'
            }]}>
            <Animated.View style={{ opacity: 0, transform: [{ rotate: '-30deg' }], position: 'absolute', top: 50, left: 40, zIndex: 1000 }}>
              <Text style={{ borderWidth: 1, borderColor: 'green', color: 'green', fontSize: 32, fontWeight: '800', padding: 10 }}>LIKE</Text>

            </Animated.View>

            <Animated.View style={{ opacity: 0, transform: [{ rotate: '30deg' }], position: 'absolute', top: 50, right: 40, zIndex: 1000 }}>
              <Text style={{ borderWidth: 1, borderColor: 'red', color: 'red', fontSize: 32, fontWeight: '800', padding: 10 }}>NOPE</Text>

            </Animated.View>

            <Image
              style={{ flex: 1, height: null, width: null, resizeMode: 'cover', borderRadius: 20 }}
              source={item.uri} />

          </Animated.View>
        )
      }
    }).reverse()
  }

  
    return (
      <View style={{ flex: 1 }}>
        <View style={{ height: 10 }}>

        </View>
        <View style={{ flex: 1 }}>
          {renderUsers()}
        </View>
        <View style={{ height: 20 }}>

        </View>


      </View>

    );
  };

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});



export default SignUpScreen;

These are all functional react native.这些都是功能性的本机反应。 Please help me solve the problems thank you very much.请帮我解决问题,非常感谢。

Here is the issue.这是问题所在。

const [position, setPosition] = useState(new Animated.ValueXY());

Rather use it而是使用它

const [position] = useState(new Animated.ValueXY());

Don't use setPosition() to update position .不要使用setPosition()更新position

setPosition(new Animated.ValueXY({x: gestureState.dx, y: gestureState.dy}));
//or
setPosition(new AnimatedValue({x: 0, y: 0 })); 

Try setValue() to update position尝试setValue()更新position

position.setValue({x: gestureState.dx, y: gestureState.dy});
//or
position.setValue({x: 0, y: 0});

I did the same, it worked我也是这样做的,成功了

Try the following, addition with @Kangkan Lahkar solution,尝试以下,加上@Kangkan Lahkar 解决方案,

position.setValue({x: gestureState.dx, y: gestureState.dy});
//or 
position.setValue({x: 0, y: 0});

separate this into 2 separate transform:将其分成2个单独的变换:

const rotateAndTranslate = {
  transform: [{
    rotate: rotate
  },
  ...position.getTranslateTransform()
  ]
}

and apply to 2 different style container in the same panResponder eg:并应用于同一个 panResponder 中的 2 个不同样式的容器,例如:

<Animated.View {...panResponder.panHandlers}
   style={[...position.getTranslateTransform()]}>

   <Animated.View style={{ ... transform:[{rotate: rotate}] }}> ....</Animated.View> 

</Animated.View>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM