reactjs – 如何在React Native中使用多个视图进行拖放?

前端之家收集整理的这篇文章主要介绍了reactjs – 如何在React Native中使用多个视图进行拖放?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我在动态相同位置添加了多个视图,还添加了pan Gesture的每个视图.所有视图在同一位置,以便覆盖.我的问题是,当想要拖动最后一个视图时,它会拖动所有视图.如何拖动单个视图.

在这里你可以看到所有视图的GIF. View1,View 2和View 3.所有都是拖动.我想只查看3是可拖动的,其他拖动完成后拖3.

1.拖动3 – 首先拖动.

2.拖动2 – 拖动.

3.拖动1 – 第三次拖动.

代码

import React,{ Component } from 'react';
import {
  StyleSheet,View,Text,PanResponder,Animated,Easing,Dimensions,Platform,TouchableOpacity,} from 'react-native';

let CIRCLE_RADIUS = 36;
let Window = Dimensions.get('window');
const instructions = Platform.select({
  ios: 'Press Cmd+R to reload,\n' +
    'Cmd+D or shake for dev menu',android: 'Double tap R on your keyboard to reload,\n' +
    'Shake or press menu button for dev menu',});

export default class App extends Component<{}> {
  constructor(props){
    super(props);

    this.state = {
        showDraggable   : true,dropZoneValues  : null,pan             : new Animated.ValueXY(),dataDrag        : [1,2,3,4],};

    this.panResponder = PanResponder.create({
        onStartShouldSetPanResponder    : () => true,onPanResponderMove              : Animated.event([null,{
            dx  : this.state.pan.x,dy  : this.state.pan.y
        }]),onPanResponderRelease           : (e,gesture) => {
            if(this.isDropZone(gesture)){
                this.setState({
                    showDraggable : false
                });
            }else{
                Animated.spring(
                    this.state.pan,{toValue:{x:0,y:0}}
                ).start();
            }
        }
    });
}

isDropZone(gesture){
    var dz = this.state.dropZoneValues;
    return gesture.moveY > dz.y && gesture.moveY < dz.y + dz.height;
}

setDropZoneValues(event){
    this.setState({
        dropZoneValues : event.nativeEvent.layout
    });
}

render(){
    return (
        <View style={styles.mainContainer}>
            <View
                onLayout={this.setDropZoneValues.bind(this)}
                style={styles.dropZone}>
                <Text style={styles.text}>Drop me here!</Text>
            </View>

            {this.state.dataDrag.map((d,index) => (
              <View key = {index} style={styles.draggableContainer}>
                  <Animated.View
                      {...this.panResponder.panHandlers}
                      style={[this.state.pan.getLayout(),styles.circle]}>
                      <Text style={styles.text}>Drag {index}</Text>
                  </Animated.View>
              </View>
            ))}


        </View>
    );
}

renderDraggable(){
    //if(this.state.showDraggable){
        return (
            <View style={styles.draggableContainer}>
                <Animated.View
                    {...this.panResponder.panHandlers}
                    style={[this.state.pan.getLayout(),styles.circle]}>
                    <Text style={styles.text}>Drag me!</Text>
                </Animated.View>
            </View>
        );
    //}
  }
}

let styles = StyleSheet.create({
    mainContainer: {
        flex    : 1
    },dropZone    : {
        height  : 100,backgroundColor:'#2c3e50'
    },text        : {
        marginTop   : 25,marginLeft  : 5,marginRight : 5,textAlign   : 'center',color       : '#fff'
    },draggableContainer: {
        position    : 'absolute',top         : Window.height/2 - CIRCLE_RADIUS,left        : Window.width/2 - CIRCLE_RADIUS,},circle      : {
        backgroundColor     : '#1abc9c',width               : CIRCLE_RADIUS*2,height              : CIRCLE_RADIUS*2,borderRadius        : CIRCLE_RADIUS
    },});

GIF:

我想低于结果:

有几个地方需要修改才能使它工作.

一步步:

>你的四个圆圈占据了自己的位置.所以4
Animated.ValueXY是必需的.

this.dataDrag = [1,4];
this.pan = this.dataDrag.map( () => new Animated.ValueXY() );

>您的PanResponder需要当前索引的信息.把它拉出来
返回包含索引信息的函数函数.

getPanResponder(index) {
    return PanResponder.create({
        onStartShouldSetPanResponder: () => true,onPanResponderMove: Animated.event([null,{
            dx: this.pan[index].x,dy: this.pan[index].y
        }]),onPanResponderRelease : (e,gesture) => {
            if(this.isDropZone(gesture)){
                this.setState({
                    showDraggable : false
                });
            }else{
                Animated.spring(
                    this.pan[index],y:0}}
                ).start();
            }
        }
    });    
}

>根据以上变化制作你的风格.删除外部视图,这是不必要的,也阻止事件.

{this.dataDrag.map((d,index) => (
    <Animated.View
        key={index}
        {...this.getPanResponder(index).panHandlers}
        style={[styles.draggableContainer,this.pan[index].getLayout(),styles.circle]}>
        <Text style={styles.text}>Drag {index}</Text>
    </Animated.View>
))}

>做边距技巧以减少位置计算.将top / left更改为marginTop / marginLeft.

draggableContainer: {
    position    : 'absolute',marginTop   : Window.height/2 - CIRCLE_RADIUS,marginLeft  : Window.width/2 - CIRCLE_RADIUS,

最终守则:

import React,{ Component } from 'react';
import {
    StyleSheet,} from 'react-native';

let CIRCLE_RADIUS = 36;
let Window = Dimensions.get('window');

export class App extends Component<{}> {
    constructor(props){
        super(props);

        this.dataDrag = [1,4];
        this.pan = this.dataDrag.map( () => new Animated.ValueXY() );

        this.state = {
            showDraggable   : true,};
    }

    getPanResponder(index) {
        return PanResponder.create({
            onStartShouldSetPanResponder: () => true,{
                dx  : this.pan[index].x,dy  : this.pan[index].y
            }]),gesture) => {
                if(this.isDropZone(gesture)){
                    this.setState({
                        showDraggable : false
                    });
                }else{
                    Animated.spring(
                        this.pan[index],y:0}}
                    ).start();
                }
            }
        });    
    }

    isDropZone(gesture){
        var dz = this.state.dropZoneValues;
        return gesture.moveY > dz.y && gesture.moveY < dz.y + dz.height;
    }

    setDropZoneValues(event){
        this.setState({
            dropZoneValues : event.nativeEvent.layout
        });
    }

    render(){
        return (
            <View style={styles.mainContainer}>
                <View
                    onLayout={this.setDropZoneValues.bind(this)}
                    style={styles.dropZone}>
                    <Text style={styles.text}>Drop me here!</Text>
                </View>

                {this.dataDrag.map((d,index) => (
                    <Animated.View
                        key={index}
                        {...this.getPanResponder(index).panHandlers}
                        style={[styles.draggableContainer,styles.circle]}>
                        <Text style={styles.text}>Drag {index}</Text>
                    </Animated.View>
                ))}
            </View>
        );
    }
}

let styles = StyleSheet.create({
    mainContainer: {
        flex    : 1
    },marginTop         : Window.height/2 - CIRCLE_RADIUS,marginLeft        : Window.width/2 - CIRCLE_RADIUS,});

结果:

猜你在找的React相关文章