我在同一位置动态添加了多个视图,还添加了 平移手势每个视图。所有视图位于同一位置,因此可以 覆盖。我的问题是,当要拖动最后一个视图时,却 拖动了所有视图。如何拖动单个视图。
在这里您可以看到所有视图中的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 }, });
有几个地方需要修改以使其起作用。
this.dataDrag = [1,2,3,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], {toValue:{x:0,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, 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 }, });