我在动态相同位置添加了多个视图,还添加了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,});
结果: