当前位置: 首页 > 面试题库 >

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

邓光赫
2023-03-14
问题内容

我在同一位置动态html" target="_blank">添加了多个视图,还添加了
平移手势每个视图。所有视图位于同一位置,因此可以
覆盖。我的问题是,当要拖动最后一个视图时,却
拖动了所有视图。如何拖动单个视图。

在这里您可以看到所有视图中的GIF。View1,View 2和View3。所有都在
拖动。我只希望视图3是可拖动的,其他人则在
拖动3 完成后拖动。

1.拖动3-第一个拖动。

2.拖动2-第二次拖动。

3.拖动1-第三次拖动。

代码:
Code :

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
    },
});

问题答案:

有几个地方需要修改以使其起作用。

Step by Step:

  1. 您的四个圈子拥有自己的位置。因此Animated.ValueXY需要4 。
        this.dataDrag = [1,2,3,4];
    this.pan = this.dataDrag.map( () => new Animated.ValueXY() );
  1. PanResponder需要当前索引中的信息。将其拉出作为返回包含info信息的函数的函数index。
        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],
                        {toValue:{x:0,y:0}}
                    ).start();
                }
            }
        });    
    }
  1. 根据上述变化制作样式。删除不必要的外部视图以及阻塞事件。
        {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>
    ))}
  1. 做保证金技巧以减少头寸的计算。更改top / left为marginTop / marginLeft
        draggableContainer: {
        position    : 'absolute',
        marginTop   : Window.height/2 - CIRCLE_RADIUS,
        marginLeft  : Window.width/2 - CIRCLE_RADIUS,
    },

Final Code:

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');

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

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

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

    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],
                        {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.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>
                ))}
            </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',
        marginTop         : Window.height/2 - CIRCLE_RADIUS,
        marginLeft        : Window.width/2 - CIRCLE_RADIUS,
    },
    circle      : {
        backgroundColor     : '#1abc9c',
        width               : CIRCLE_RADIUS*2,
        height              : CIRCLE_RADIUS*2,
        borderRadius        : CIRCLE_RADIUS
    },
});


 类似资料:
  • 问题内容: 我使用gridview显示数字,因此,如果我单击任何数字,则下一个活动应该开始。我尝试了此代码,但应用程序崩溃 这是gridview的xml代码 logcat文件日志 问题答案: GridView就像ListView 你应该用这样的东西 代码不完美 供参考,请参阅http://developer.android.com/reference/android/widget/GridView

  • 本文向大家介绍如何在Selenium中进行拖放动作?,包括了如何在Selenium中进行拖放动作?的使用技巧和注意事项,需要的朋友参考一下 我们可以借助Actions类在Selenium中执行拖放动作。为了执行拖放运动,我们将使用dragAndDrop(源,目标)方法。最后,使用.perform()执行所有步骤。 示例

  • 问题内容: 我正在设置标头和正文,使用Post提取将图像上传到服务器上。我得到的响应码是200,但它不是上传图像,而是其余数据正在上传。 这是正文的代码: 请帮助。我正在犯什么错误。:( 问题答案: 我找到了解决方案: **文件名是可选的…

  • 我使用的是WPF ListView,其中SelectionMode设置为Extended(只能按ctrl键选择多个项目)。我需要实施D 不幸的是,这样的解决方案有一个错误:选择单个项目(未按 ctrl)有效。但是,我需要双击以选择项目,同时按ctrl才能选择多个项目。使用 ListView 的 PreviewMouseDown 或 ListViewItem 的 PreviewMouseDown 时

  • 问题内容: 如何设置JTable以便能够将行拖到表中的其他索引。例如,如果我有5行,并且想将第4行拖到第2个位置? 问题答案: 查看Java教程的拖放部分。有关如何实现此功能的示例有一些。

  • 问题内容: 我想对pandas进行一次透视,索引是两列,而不是一列。例如,一个字段用于年份,一个字段用于月份,一个“ item”字段显示“ item 1”和“ item 2”,以及一个“ value”字段和数值。我希望索引为年+月。 我设法做到这一点的唯一方法是将两个字段合并为一个,然后再次将其分开。有没有更好的办法? 最少的代码复制到下面。非常感谢! PS:是的,我知道关键字“ pivot”和“