代码之家  ›  专栏  ›  技术社区  ›  mr_js

使用react native的可拖动组件出现问题-使用动画和PanResponder实现

  •  1
  • mr_js  · 技术社区  · 6 年前

    从中汲取灵感 this 问题,我在视图中实现了两个可拖动的组件。父视图如下:

    import React, { Component } from "react";
    import { Text, View, StyleSheet, Dimensions } from "react-native";
    import Draggable from "./Draggable";
    
    export default class FloorPlan extends Component {
      constructor() {
        super();
        const { width, height } = Dimensions.get("window");
        this.separatorPosition = (height * 2) / 3;
      }
    
      render() {
        return (
          <View style={styles.mainContainer}>
            <View style={[...styles.dropZone, { height: this.separatorPosition }]}>
              <Text style={styles.text}>Floor plan</Text>
            </View>
            <View style={styles.drawerSeparator} />
            <View style={styles.row}>
              <Draggable />
              <Draggable />
            </View>
          </View>
        );
      }
    }
    
    const styles = StyleSheet.create({
      mainContainer: {
        flex: 1
      },
      drawerSeparator: {
        backgroundColor: "grey",
        height: 20
      },
      row: {
        flexDirection: "row",
        marginTop: 25
      },
      dropZone: {
        height: 700,
        backgroundColor: "#f4fffe"
      },
      text: {
        marginTop: 25,
        marginLeft: 5,
        marginRight: 5,
        textAlign: "center",
        color: "grey",
        fontSize: 20
      }
    });

    可拖动组件实现如下:

    import React, { Component } from "react";
    import {
      StyleSheet,
      View,
      PanResponder,
      Animated,
      Text,
      Dimensions
    } from "react-native";
    
    export default class Draggable extends Component {
      constructor() {
        super();
        const { width, height } = Dimensions.get("window");
        this.separatorPosition = (height * 2) / 3;
        this.state = {
          pan: new Animated.ValueXY(),
          circleColor: "skyblue"
        };
        this.currentPanValue = { x: 0, y: 0 };
        this.panListener = this.state.pan.addListener(
          value => (this.currentPanValue = value)
        );
      }
    
      componentWillMount() {
        this.state.pan.removeListener(this.panListener);
      }
    
      componentWillMount() {
        this.panResponder = PanResponder.create({
          onStartShouldSetPanResponder: (evt, gestureState) => false,
          onMoveShouldSetPanResponder: (evt, gestureState) => false,
          onMoveShouldSetPanResponderCapture: (evt, gesture) => {
            return true;
          },
          onPanResponderGrant: (e, gestureState) => {
            this.setState({ circleColor: "red" });
          },
          onPanResponderMove: (event, gesture) => {
            Animated.event([
              null,
              {
                dx: this.state.pan.x,
                dy: this.state.pan.y
              }
            ])(event, gesture); 
          },
          onPanResponderRelease: (event, gesture) => {
            this.setState({ circleColor: "skyblue" });
            if (gesture.moveY < this.separatorPosition) {
              this.state.pan.setOffset({
                x: this.currentPanValue.x,
                y: this.currentPanValue.y
              });
              this.state.pan.setValue({ x: 0, y: 0 });
              // this.state.pan.flattenOffset();
            } else {
              //Return icon to start position
              this.state.pan.flattenOffset();
              Animated.timing(this.state.pan, {
                toValue: {
                  x: 0,
                  y: 0
                },
                useNativeDriver: true,
                duration: 200
              }).start();
            }
          }
        });
      }
    
      render() {
        const panStyle = {
          transform: this.state.pan.getTranslateTransform()
        };
        return (
          <Animated.View
            {...this.panResponder.panHandlers}
            style={[
              panStyle,
              styles.circle,
              { backgroundColor: this.state.circleColor }
            ]}
          />
        );
      }
    }
    
    let CIRCLE_RADIUS = 30;
    let styles = StyleSheet.create({
      circle: {
        backgroundColor: "skyblue",
        width: CIRCLE_RADIUS * 2,
        height: CIRCLE_RADIUS * 2,
        borderRadius: CIRCLE_RADIUS,
        marginLeft: 25
      }
    });

    一个可拖动的组件可以被拖到平面图上,它的位置将在下一个平移操作中被记住。但是,在拖动过程中,有时会出现故障,图标会在平移开始时跳跃或完全消失。

    有什么问题吗?我正在使用React Native 0.55.2进行开发,并使用运行Android7的设备进行测试。

    0 回复  |  直到 6 年前