在 React Native 中同时拖放多个

Multiple drag and drop simultaneous in React Native

你好,我正在用 React Native 创建一个游戏,但我被卡住了,因为我不想两个玩家都可以在同一时间水平拖放一个元素 phone。

我有两个这样的组件:

export class Player1 extends Component{
    constructor(props){
        super(props);

        this.state = {  
            pan             : new Animated.ValueXY()
        };
    }
    componentWillMount(){
        this.panResponder = PanResponder.create({    
            onMoveShouldSetResponderCapture : () => true,
            onMoveShouldSetPanResponderCapture : () => true,

            onPanResponderGrant : (e, gestureState) => {
                this.state.pan.setOffset({x: this.state.pan.x._value, y: this.state.pan.y._value});
                this.state.pan.setValue({x: 0, y: 0});
            },

            onPanResponderMove : Animated.event([null,{ 
                dx : this.state.pan.x,
            }]),
            onPanResponderRelease: (e, {vx, vy}) => {
            }
        });
    }


    render(){
        return (
                <View style={styles.mainContainer}>
                    {this.renderDraggable()}
                </View>
        );
    }

    renderDraggable(){
        return (
                <View style={styles.draggableContainer}>
                    <Animated.View                  
                    style={[this.state.pan.getLayout(), styles.triangle]}
                    {...this.panResponder.panHandlers}   > 
                    </Animated.View>
            </View>

        );
}
}

在我的屏幕上,我这样称呼我的组件:

export default function HomeScreen() {
  return (
    <View>
     <Player1></Player1>
     <Player2></Player2>
    </View>
  );
}

感谢您的帮助

我找到了一个解决方案,我使用了 react-native-gesture-handler 就像在示例的目录 double Draggable 中:https://kmagiera.github.io/react-native-gesture-handler/docs/example.html

我的代码:

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

import {
  PanGestureHandler,
  ScrollView,
  State,
} from 'react-native-gesture-handler';


export class Players extends Component {
  constructor(props) {
    super(props);
    this._translateX = new Animated.Value(0);
    this._translateY = new Animated.Value(0);
    this._lastOffset = { x: 0, y: 0 };
    this._onGestureEvent = Animated.event(
      [
        {
          nativeEvent: {
            translationX: this._translateX,

          },
        },
      ],

    );
  }
  _onHandlerStateChange = event => {
    if (event.nativeEvent.oldState === State.ACTIVE) {
      this._lastOffset.x += event.nativeEvent.translationX;
      this._translateX.setOffset(this._lastOffset.x);
      this._translateX.setValue(0);
      this._translateY.setOffset(this._lastOffset.y);
      this._translateY.setValue(0);
    }
  };
  render() {
    return (
      <PanGestureHandler
        {...this.props}
        onGestureEvent={this._onGestureEvent}
        onHandlerStateChange={this._onHandlerStateChange}>
        <Animated.View
          style={[
            styles.box,
            {
              transform: [
                { translateX: this._translateX },
                { translateY: this._translateY },
              ],
            },
            this.props.boxStyle,
          ]}
        />
      </PanGestureHandler>
    );
  }
}

export default class Example extends Component {
  render() {
    return (
      <View style={styles.scrollView}>
        <DraggableBox />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  scrollView: {
    flex: 1,
  },
  box: {
    position: 'absolute',
    width: 0,
    height: 0,
    backgroundColor: 'transparent',
    borderStyle: 'solid',
    borderLeftWidth: 25,
    borderRightWidth: 25,
    borderBottomWidth: 50,
    borderLeftColor: 'transparent',
    borderRightColor: 'transparent',
  },
});

和屏幕:

<View styles={styles.container}>
  <Players boxStyle={styles.player1}></Players>
  <Players boxStyle={styles.player2}></Players>
</View>

这几天我一直在无休止地寻找类似的东西,但我找不到 react-native-gesture-handler 提供的这些演示。非常感谢@Lillian Pacaud 在这里发布这篇文章。这是他们的几个演示的 link,包括可拖动组件:https://snack.expo.dev/@adamgrzybowski/react-native-gesture-handler-demo

如果您同时需要任何 presses/gesture/drags/etc...您最好的选择是使用 react-native-gesture-handler 因为本机实现的所有 touch/gesture-based 组件在本机反应中不允许与每个人同时互动,尤其是 Android.

我制作了一个功能组件,其功能与已接受的答案相同。只需将任何你想作为组件下的子元素拖动即可。它可以处理同时拖动以及 iOS 和 Android.

上接受的答案

拖拽组件使用示例:

import React from 'react';
import { View } from 'react-native';

import { DraggableTest } from '../components/test';

export default function Screen() {
  return (
    <View style={{ flex: 1 }}>
      <DraggableTest>
        <View
          style={{ width: 150, height: 150, backgroundColor: 'lime' }}
        />
      </DraggableTest>
    </View>
  );
}

可拖动组件:

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

import { PanGestureHandler, State } from 'react-native-gesture-handler';

export function DraggableTest({ children }) {
  const pan = useRef(new Animated.ValueXY()).current;
  const lastOffset = useRef({ x: 0, y: 0 }).current;

  const onGestureEvent = Animated.event(
    [{ nativeEvent: { translationX: pan.x, translationY: pan.y } }],
    { useNativeDriver: false },
  );

  const onHandlerStateChange = event => {
    if (event.nativeEvent.oldState == State.ACTIVE) {
      lastOffset.x += event.nativeEvent.translationX;
      lastOffset.y += event.nativeEvent.translationY;
      pan.setOffset({ x: lastOffset.x, y: lastOffset.y });
      pan.setValue({ x: 0, y: 0 });
    }
  };

  return (
    <PanGestureHandler
      onGestureEvent={onGestureEvent}
      onHandlerStateChange={onHandlerStateChange}>
      <Animated.View style={[pan.getLayout(), styles.animatedView]}>
        {children}
      </Animated.View>
    </PanGestureHandler>
  );
}

const styles = StyleSheet.create({
  animatedView: {
    position: 'absolute',
  },
});