React native 反应本机拖放多个项目

React native 反应本机拖放多个项目,react-native,drag-and-drop,React Native,Drag And Drop,我试着做两个圆圈,可以拖动和下降与反应本机 我本可以创建一个可以拖放的圆,但不知道如何分别创建两个圆 这是一个可以拖放的圆的代码 constructor(props){ super(props); this.state = { pan : new Animated.ValueXY() //Step 1 }; this.panResponder = PanResponder.create({ //Step 2 onStartShouldS

我试着做两个圆圈,可以拖动和下降与反应本机

我本可以创建一个可以拖放的圆,但不知道如何分别创建两个圆

这是一个可以拖放的圆的代码

constructor(props){
  super(props);
  this.state = {
      pan     : new Animated.ValueXY()   //Step 1
  };

  this.panResponder = PanResponder.create({    //Step 2
      onStartShouldSetPanResponder : () => true,
      onPanResponderMove           : Animated.event([null,{ //Step 3
          dx : this.state.pan.x,
          dy : this.state.pan.y
        }]),

      onPanResponderRelease        : (e, gesture) => {} //Step 4
  });
}
这是为了形象

renderDraggable(){
 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>
 );
}
renderDraggable(){
返回(
拖我!
);
}
从“React”导入React,{Component};
进口{
样式表,
文本,
看法
Image,//我们要使用一个映像
PanResponder,//我们要引入PanResponder系统
动画//我们将使用动画值
}从“反应本机”;
导出默认类MovingCircle扩展React.Component{
建造师(道具){
超级(道具);
此.state={
平移:新的动画.ValueXY(),
比例:新动画。值(1)
};
}
_handleStartShouldSetPanResponder(e,手势状态){
返回true;
}
_handleMoveShouldSetPanResponder(e,手势状态){
返回true;
}
组件willmount(){
这是.\u panResponder=panResponder.create({
onStartShouldSetPanResponder:
此._handlestart应设置panresponder.bind(此),
onMoveShouldSetPanResponder:
此._handleMove应设置PanResponder.bind(此),
onPanResponderGrant:(e,手势状态)=>{
//将初始值设置为当前状态
setOffset({x:this.state.pan.x._值,y:this.state.pan.y._值});
this.state.pan.setValue({x:30*Math.random(),y:0});
春天(
这个州的规模,
{toValue:1.1,摩擦力:1}
).start();
},
//拖动/平移对象时,将三角形设置为状态平移位置
onPanResponderMove:Animated.event([
null,{dx:this.state.pan.x,dy:this.state.pan.y},
]),
onPanResponderRelease:(e,{vx,vy})=>{
//展平偏移以避免不稳定的行为
this.state.pan.flattOffset();
春天(
这个州的规模,
{toValue:1,摩擦力:1}
).start();
}
});
}
render(){
//从状态中解构pan的值
设{pan,scale}=this.state;
//根据平移值计算x和y变换
设[translateX,translateY]=[pan.x,pan.y];
让旋转='0度';
//计算transform属性并将其设置为样式的值,我们在下面将其添加到动画.View组件中
让imageStyle={transform:[{translateX},{translateY},{rotate},{scale}]};
返回(
tgyyHH
);
}
}
const styles=StyleSheet.create({
容器:{
宽度:50,
身高:50,
位置:'绝对'
},
矩形:{
边界半径:4,
边框宽度:1,
边框颜色:“#fff”,
宽度:50,
身高:50,
背景颜色:“#68a0cf”,
},
txt:{
颜色:“#fff”,
textAlign:“中心”
}
});

以下是如何使项目相互独立。这个例子是用typescript编写的,但是应该足够清晰,可以转换成纯javascript。这里的主要思想是,每个动画项都需要自己的PanResponderInstance,一旦更新了这些项,还需要刷新PanResponderInstance

interface State {
    model: Array<MyAnimatedItem>,
    pans: Array<Animated.ValueXY>,
    dropZone1: LayoutRectangle,
    dropZone2: LayoutRectangle,
}

public render(): JSX.Element {

    const myAnimatedItems = new Array<JSX.Element>()
    for (let i = 0; i < this.state.model.length; i++) {
        const item = this.state.model[i]
        const inst = this.createResponder(this.state.pans[i], item)
        myAnimatedItems.push(
            <Animated.View
                key={'item_' + i}
                {...inst.panHandlers}
                style={this.state.pans[i].getLayout()}>
                <Text>{item.description}</Text>
            </Animated.View>
        )
    }

    return (
        <View>
            <View onLayout={this.setDropZone1} style={styles.dropZone}>
                <View style={styles.draggableContainer}>
                    {myAnimatedItems}
                </View>
            </View>
            <View onLayout={this.setDropZone2} style={styles.dropZone}>
                <View style={styles.draggableContainer}>
                    ...
                </View>
            </View>
        </View>
    )
}

private setDropZone1 = (event: LayoutChangeEvent): void => {
    this.setState({
        dropZone1: event.nativeEvent.layout
    })
}

private setDropZone2 = (event: LayoutChangeEvent): void => {
    this.setState({
        dropZone2: event.nativeEvent.layout
    })
}

private isDropZone(gesture: PanResponderGestureState, dropZone: LayoutRectangle): boolean {
    const toolBarHeight = variables.toolbarHeight + 15 // padding
    return gesture.moveY > dropZone.y + toolBarHeight
        && gesture.moveY < dropZone.y + dropZone.height + toolBarHeight
        && gesture.moveX > dropZone.x
        && gesture.moveX < dropZone.x + dropZone.width
}

private createResponder(pan: Animated.ValueXY, item: MyAnimatedItem): PanResponderInstance {
    return PanResponder.create({
        onStartShouldSetPanResponder: () => true,
        onPanResponderMove: Animated.event([null, {
            dx: pan.x,
            dy: pan.y
        }]),
        onPanResponderRelease: (_e, gesture: PanResponderGestureState) => {
            const model = this.state.model
            const pans = this.state.pans
            const idx = model.findIndex(x => x.id === item.id)

            if (this.isDropZone(gesture, this.state.dropZone1)) {
                ... // do something with the item if needed
                // reset each PanResponderInstance
                for (let i = 0; i < model.length; i++) {
                    pans[i] = new Animated.ValueXY()
                }
                this.setState({ model: model, pans: pans })
                return
                }
            } else if (this.isDropZone(gesture, this.state.dropZone2)) {
                ... // do something with the item if needed
                    // reset each PanResponderInstance
                for (let i = 0; i < model.length; i++) {
                    pans[i] = new Animated.ValueXY()
                }
                this.setState({ model: model, pans: pans })
                return
            }

            Animated.spring(pan, { toValue: { x: 0, y: 0 } }).start()
            this.setState({ scrollEnabled: true })
        }
    })
}
接口状态{
型号:阵列,
pans:数组,
dropZone1:布局延伸角度,
dropZone2:布局延伸角度,
}
public render():JSX.Element{
const myAnimatedItems=新数组()
for(设i=0;i{
这是我的国家({
dropZone1:event.nativeEvent.layout
})
}
私有setDropZone2=(事件:LayoutChangeEvent):void=>{
这是我的国家({
dropZone2:event.nativeEvent.layout
})
}
private isDropZone(手势:PanResponderGetSturEstate,dropZone:LayoutRectangle):布尔值{
const toolBarHeight=variables.toolBarHeight+15//填充
返回手势.moveY>dropZone.y+toolBarHeight
&&手势.moveYdropZone.x
&&手势.moveXtrue,
onPanResponderMove:Animated.event([null{
dx:pan.x,
戴:潘。y
}]),
onPanResponderRelease:(\u e,手势:PanResponderGetSturEstate)=>{
常量模型=this.state.model
const pans=this.state.pans
const idx=model.findIndex(x=>x.id==item.id)
if(this.isDropZone(手势,this.state.dropZone1)){
…//如果需要,可以对该项执行某些操作
//重置每个PanResponderInstance
for(设i=0;i
您好,谢谢您的评论。这是非常有用的,但是我如何制作两个可以单独移动的不同图像呢
interface State {
    model: Array<MyAnimatedItem>,
    pans: Array<Animated.ValueXY>,
    dropZone1: LayoutRectangle,
    dropZone2: LayoutRectangle,
}

public render(): JSX.Element {

    const myAnimatedItems = new Array<JSX.Element>()
    for (let i = 0; i < this.state.model.length; i++) {
        const item = this.state.model[i]
        const inst = this.createResponder(this.state.pans[i], item)
        myAnimatedItems.push(
            <Animated.View
                key={'item_' + i}
                {...inst.panHandlers}
                style={this.state.pans[i].getLayout()}>
                <Text>{item.description}</Text>
            </Animated.View>
        )
    }

    return (
        <View>
            <View onLayout={this.setDropZone1} style={styles.dropZone}>
                <View style={styles.draggableContainer}>
                    {myAnimatedItems}
                </View>
            </View>
            <View onLayout={this.setDropZone2} style={styles.dropZone}>
                <View style={styles.draggableContainer}>
                    ...
                </View>
            </View>
        </View>
    )
}

private setDropZone1 = (event: LayoutChangeEvent): void => {
    this.setState({
        dropZone1: event.nativeEvent.layout
    })
}

private setDropZone2 = (event: LayoutChangeEvent): void => {
    this.setState({
        dropZone2: event.nativeEvent.layout
    })
}

private isDropZone(gesture: PanResponderGestureState, dropZone: LayoutRectangle): boolean {
    const toolBarHeight = variables.toolbarHeight + 15 // padding
    return gesture.moveY > dropZone.y + toolBarHeight
        && gesture.moveY < dropZone.y + dropZone.height + toolBarHeight
        && gesture.moveX > dropZone.x
        && gesture.moveX < dropZone.x + dropZone.width
}

private createResponder(pan: Animated.ValueXY, item: MyAnimatedItem): PanResponderInstance {
    return PanResponder.create({
        onStartShouldSetPanResponder: () => true,
        onPanResponderMove: Animated.event([null, {
            dx: pan.x,
            dy: pan.y
        }]),
        onPanResponderRelease: (_e, gesture: PanResponderGestureState) => {
            const model = this.state.model
            const pans = this.state.pans
            const idx = model.findIndex(x => x.id === item.id)

            if (this.isDropZone(gesture, this.state.dropZone1)) {
                ... // do something with the item if needed
                // reset each PanResponderInstance
                for (let i = 0; i < model.length; i++) {
                    pans[i] = new Animated.ValueXY()
                }
                this.setState({ model: model, pans: pans })
                return
                }
            } else if (this.isDropZone(gesture, this.state.dropZone2)) {
                ... // do something with the item if needed
                    // reset each PanResponderInstance
                for (let i = 0; i < model.length; i++) {
                    pans[i] = new Animated.ValueXY()
                }
                this.setState({ model: model, pans: pans })
                return
            }

            Animated.spring(pan, { toValue: { x: 0, y: 0 } }).start()
            this.setState({ scrollEnabled: true })
        }
    })
}