如何在React native中创建拖放操作?

时间:2022-08-22 20:21:16

Say I have two Views, A and B. I want to have the ability to trigger a 'dragAndDropStart' event on touching View A and then enable a drag and drop from A to B... displaying feedback to the user throughout (i.e. showing a line appearing between View A and the user's finger). On drop (releasing the drag gesture) I want to trigger another 'dragAndDropEnd' event, this time on View B.

假设我有两个视图,A和B.我希望能够在触摸视图A时触发'dragAndDropStart'事件,然后启用从A到B的拖放...在整个过程中向用户显示反馈(即显示在视图A和用户手指之间出现的一条线)。在放下(释放拖动手势)我想触发另一个'dragAndDropEnd'事件,这次是在View B上。

如何在React native中创建拖放操作?

The touchStart and touchEnd handlers are too limited as they don't appear to permit handoff of the gesture from one View to another. They also don't seem to enable the in-between 'drag' state.

touchStart和touchEnd处理程序太有限了,因为它们似乎不允许将手势从一个View切换到另一个View。它们似乎也没有启用中间“拖动”状态。

The React native docs on using the gesture handlers is a little cryptic and I haven't seen any examples that demonstrate their use.

关于使用手势处理程序的React原生文档有点神秘,我没有看到任何证明它们使用的示例。

Any ideas?

有任何想法吗?

2 个解决方案

#1


15  

export default class Viewport extends Component{
    constructor(props){
        super(props);

        this.state = {
            showDraggable   : true,
            dropZoneValues  : null,
            pan             : new Animated.ValueXY()
        };

        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.renderDraggable()}
            </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>
            );
        }
    }
}

source http://moduscreate.com/animated_drag_and_drop_with_react_native/

来源http://moduscreate.com/animated_drag_and_drop_with_react_native/

https://github.com/crysfel/DragAndDrop

https://github.com/crysfel/DragAndDrop

#2


-4  

you have to see the current View Rectangle to other view Rectangle if one of your view rectangle intersect each other at some point it will return true then you get notify that the A view was drag to B view here is my example code may be it will help you .

你必须看到当前的视图矩形到其他视图矩形,如果你的一个视图矩形在某个点相互交叉它将返回true然后你得到通知A视图被拖到B视图这里是我的示例代码可能它会帮你 。

-(void)moveViewWithGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer{

// your current View touch location suppose View A
    CGPoint touchLocation = [panGestureRecognizer locationInView:self.contentView];

    CGRect movingAViewRect = CGRectMake(touchLocation.x, touchLocation.y, self.aView.width, self.aView.height);

 //   NSLog(@"Point not Matched first => %@  and second => %@",NSStringFromCGPoint(touchLocation),NSStringFromCGPoint(self.bView.frame.origins));
    self.aView.center = touchLocation;
      

    if(panGestureRecognizer.state == UIGestureRecognizerStateEnded)
    {
        //All fingers are lifted.
      
    

        if(CGRectIntersectsRect(movingAViewRect,self.bView.frame)){
     
            NSLog(@"Point Matched first => %@  and second => %@",NSStringFromCGRect(movingAViewRect),NSStringFromCGRect (self.bView.frame ));

       // and here you can perform some action for this 
            
            
        }else{
        
            NSLog(@"aView is not drag on bView please drag aView to bView ");
            

        }
      
        
     
       
    }
}
  

#1


15  

export default class Viewport extends Component{
    constructor(props){
        super(props);

        this.state = {
            showDraggable   : true,
            dropZoneValues  : null,
            pan             : new Animated.ValueXY()
        };

        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.renderDraggable()}
            </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>
            );
        }
    }
}

source http://moduscreate.com/animated_drag_and_drop_with_react_native/

来源http://moduscreate.com/animated_drag_and_drop_with_react_native/

https://github.com/crysfel/DragAndDrop

https://github.com/crysfel/DragAndDrop

#2


-4  

you have to see the current View Rectangle to other view Rectangle if one of your view rectangle intersect each other at some point it will return true then you get notify that the A view was drag to B view here is my example code may be it will help you .

你必须看到当前的视图矩形到其他视图矩形,如果你的一个视图矩形在某个点相互交叉它将返回true然后你得到通知A视图被拖到B视图这里是我的示例代码可能它会帮你 。

-(void)moveViewWithGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer{

// your current View touch location suppose View A
    CGPoint touchLocation = [panGestureRecognizer locationInView:self.contentView];

    CGRect movingAViewRect = CGRectMake(touchLocation.x, touchLocation.y, self.aView.width, self.aView.height);

 //   NSLog(@"Point not Matched first => %@  and second => %@",NSStringFromCGPoint(touchLocation),NSStringFromCGPoint(self.bView.frame.origins));
    self.aView.center = touchLocation;
      

    if(panGestureRecognizer.state == UIGestureRecognizerStateEnded)
    {
        //All fingers are lifted.
      
    

        if(CGRectIntersectsRect(movingAViewRect,self.bView.frame)){
     
            NSLog(@"Point Matched first => %@  and second => %@",NSStringFromCGRect(movingAViewRect),NSStringFromCGRect (self.bView.frame ));

       // and here you can perform some action for this 
            
            
        }else{
        
            NSLog(@"aView is not drag on bView please drag aView to bView ");
            

        }
      
        
     
       
    }
}