首页 > 解决方案 > 需要帮助:我想在 react native 中创建拖放

问题描述

我有一个 react native 的任务,其中我有一个带有多个条形的条形图,在图表下方我们有可拖动的元素,我们应该将它们拖动到条形图的单个条目上。

到目前为止我所做的是,

我有多个值的平面列表。每个平面列表项都有带有胜利原生条形图的放置区域。我有三个事件,我必须将它们拖放到平面列表可放置区域。我已经尝试使用react-native-easy-dnd ,但它在平面列表中不起作用。现在我尝试使用 PanResponder。但是当我在放置区域拖动事件时,放置区域的 panResponder 没有得到手势。这是代码示例。//父组件

import React, { Component } from "react";
import { View, StyleSheet, PanResponder, ScrollView } from "react-native";
import DragBall from "./Drag";
import DropArea from "./DropArea";
class Parent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      target: null
    }
  }
  render() {
    return (
      <ScrollView >
        <View style={styles.container}>
          <View style={{ flexDirection: "row" }}>
            <DropArea color="grey" />
            <DropArea color="blue" />
            <DropArea color="green" />
          </View>
          <View style={styles.dragContainer}>
            <DragBall value="1" target={this.state.target} />
            <DragBall value="2" target={this.state.target} />
            <DragBall value="3" target={this.state.target} />
            <DragBall value="4" target={this.state.target} />
          </View>
        </View>
      </ScrollView>
    );
  }
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#f2f2f2",
    height: "100%"
  },
  dropContainer: {
    flex: 1,
    borderBottomWidth: 2,
    borderBottomColor: "black"
  },
  dragContainer: {
    flex: 1,
    backgroundColor: "red",
    alignItems: "center",
    justifyContent: "space-around",
    flexDirection: "row",
    height: 400
  }
});
export default Parent;

// 拖动事件

import React, { Component } from "react";
import { View, Text, PanResponder, Animated, StyleSheet } from "react-native";

class Check extends Component {
  constructor(props) {
    super(props);
    this.state = {
      pan: new Animated.ValueXY()
    };
    this._val = { x: 0, y: 0 };
    this.state.pan.addListener(value => (this._val = value));
    this._panResponder = PanResponder.create({
      onStartShouldSetPanResponder: (e, gesture) => true,
      onPanResponderTerminationRequest: () => true,
      // onStartShouldSetPanResponderCapture: e => true,
      // onPanResponderTerminationRequest: () => true,
      onPanResponderTerminate:() => true,
      // adjusting delta value
      // onResponderTerminationRequest: e => fal,
      onStartShouldSetResponderCapture: e => false,
      onPanResponderGrant: (e, gesture) => {
        this.state.pan.setOffset({
          x: this._val.x,
          y: this._val.y
        });
        this.state.pan.setValue({ x: 0, y: 0 });
      },
      onPanResponderMove: Animated.event([
        null,
        { dx: this.state.pan.x, dy: this.state.pan.y }
      ]),
      onPanResponderRelease: (evt, gesture) => {
        // console.log("evt target", evt.target,  "props target", this.props.target
      }
    });
  }
  render() {
    const { viewProps } = this.props;
    return (
      <Animated.View
        {...this._panResponder.panHandlers}
        style={[
          styles.balls,
          { transform: this.state.pan.getTranslateTransform() }
        ]}
      >
        <Text style={styles.text}>{this.props.value}</Text>
      </Animated.View>
    );
  }
}

const styles = StyleSheet.create({
  balls: {
    backgroundColor: "skyblue",
    width: 60,
    height: 60,
    borderRadius: 60,
    alignItems: "center",
    justifyContent: "center"
  },
  text: {
    textAlign: "center"
  }
});

export default Check;

// 放置区域

import React, { Component } from "react";
import { View, StyleSheet, PanResponder } from "react-native";
import DragBall from "./Drag";
class DropArea extends Component {
  constructor(props) {
    super(props);
    // console.log(props)
    this._panResponder = PanResponder.create({
      onPanResponderGrant: evt => {
        console.log("=====Drop Grant=====");
      },
      onStartShouldSetPanResponder: (e, gesture) => true,
      onStartShouldSetPanResponderCapture: () => true,
      // onPanResponderTerminate: () => true,
      // onPanResponderTerminationRequest: () => true,
      onMoveShouldSetPanResponder: evt => {
        console.log("Droooooooooooooooooooop");
        return true;
      },
      onMoveShouldSetPanResponderCapture: (e, gesture) => {
        console.log("capture gesture");
      },
      onResponderReject: evt => {
        console.log("Reject=====");
      },
      // onPanResponderMove: evt => {
      //   console.log("truuuuuuuuuue");
      // },

      onPanResponderRelease: (evt, gesture) => {
        console.log("===release===");
      }
    });
  }
  // handleViewMove = event => {
  //   console.log("===================");

  //   return true;
  // };

  render() {
    return (
      <View
        style={styles(this.props).dropContainer}
        {...this._panResponder.panHandlers}
      ></View>
    );
  }
}
const styles = props =>
  StyleSheet.create({
    container: {
      flex: 1,
      backgroundColor: "#f2f2f2"
    },
    dropContainer: {
      flex: 1,
      borderBottomWidth: 2,
      borderBottomColor: "black",
      backgroundColor: props.color,
      height: 300
    },
    dragContainer: {
      flex: 1,
      width: 30,
      backgroundColor: "red",
      alignItems: "center",
      justifyContent: "space-around",
      flexDirection: "row"
    }
  });
export default DropArea;

上面的代码是简单的拖放。具有三个可拖动的动画视图和三个可放置区域。实际工作在下面的屏幕截图 。在此图像中可拖动事件是子图片和公文包图片。我必须放在每个条形图上。

标签: react-nativereact-native-flatlistreact-native-scrollview

解决方案


拖放由 pangesuter 控制器控制,以进行更多拖放,请遵循该文章

如果您想感知图表的下降,您需要自定义您提供的图表库。


推荐阅读