gpt4 book ai didi

reactjs - 如何将拖动 View 绑定(bind)到ScrollView项目中?

转载 作者:行者123 更新时间:2023-12-01 22:27:40 24 4
gpt4 key购买 nike

我创建了具有三个 View 的ScrollView。我想将拖动的 View 绑定(bind)到 ScrollView 内部,其余未拖放的 View 应保留在 ScrollView 外部。怎么可能。

查看 GIF:我想在 ScrollView 中添加draggableView。

代码:

import React, { Component } from 'react';
import {
StyleSheet,
View,
Text,
PanResponder,
Animated,
Easing,
Dimensions,
Platform,
TouchableOpacity,
ScrollView,
} from 'react-native';
import Carousel from 'react-native-snap-carousel';


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.dataDrag = [1,2,3,4],
this.pan = this.dataDrag.map( () => new Animated.ValueXY() );

this.state = {
showDraggable : true,
dropZoneValues : null,
entries : ['Apple1' , 'Apple2', 'Apple3']
};
}

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){
console.log('event.nativeEvent.layout', event.nativeEvent.layout);
this.setState({
dropZoneValues : event.nativeEvent.layout
});
}

_renderItem ({item, index}) {
return (
<View style={{width: Dimensions.get('window').width - 100 , height : 150 , backgroundColor : 'red' , marginLeft : 50 , marginRight : 50}}>
<Text style={{color : 'black' , marginTop : 20}}>{item}</Text>
</View>
);
}

render(){
return (
<View style={styles.mainContainer}>

<ScrollView>
<View onLayout={this.setDropZoneValues.bind(this)}
style={[styles.dropZone , {marginTop : 10}]}>
</View>
<View onLayout={this.setDropZoneValues.bind(this)}
style={[styles.dropZone , {marginTop : 10}]}>
</View>
<View onLayout={this.setDropZoneValues.bind(this)}
style={[styles.dropZone , {marginTop : 10}]}>
</View>
</ScrollView>


{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
},
});

enter image description here

最佳答案

其基本思想是创建两个数组,通过从一个结构中删除并复制到另一个结构来模拟移动效果。

逐步:

  1. 创建两个数组

    this.state = {
    dataDrag: [...this.dataDrag],
    dataDragged: [],
    };
  2. OnPanResponderRelease,移至新数组。

    onPanResponderRelease           : (e, gesture) => {
    if(this.isDropZone(gesture)){
    let idx = this.state.dataDrag.indexOf(index+1);
    this.setState({
    showDraggable : false,
    dataDrag: [ ...this.state.dataDrag.slice(0, idx), ...this.state.dataDrag.slice(idx+1, this.state.dataDrag.length-1) ],
    dataDragged: [...this.state.dataDragged, this.state.dataDrag[idx]],
    });
    }
  3. 创建两组 Animated.View,一组在 ScollView 内部,一组在其外部。

最终代码:

import React, { Component } from 'react';
import {
StyleSheet,
View,
Text,
PanResponder,
Animated,
Easing,
Dimensions,
Platform,
TouchableOpacity,
ScrollView,
} 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,
entries : ['Apple1' , 'Apple2', 'Apple3'],
dataDrag: [...this.dataDrag],
dataDragged: [],
};
}

getPanResponder(index) {
return PanResponder.create({
onStartShouldSetPanResponder: () => {
return true;
},
onPanResponderMove : Animated.event([null,{
dx : this.pan[index].x,
dy : this.pan[index].y
}]),
onPanResponderRelease : (e, gesture) => {
if(this.isDropZone(gesture)){
let idx = this.state.dataDrag.indexOf(index+1);
this.setState({
showDraggable : false,
dataDrag: [ ...this.state.dataDrag.slice(0, idx), ...this.state.dataDrag.slice(idx+1, this.state.dataDrag.length-1) ],
dataDragged: [...this.state.dataDragged, this.state.dataDrag[idx]],
});
}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
});
}

_renderItem ({item, index}) {
return (
<View style={{width: Dimensions.get('window').width - 100 , height : 150 , backgroundColor : 'red' , marginLeft : 50 , marginRight : 50}}>
<Text style={{color : 'black' , marginTop : 20}}>{item}</Text>
</View>
);
}

render(){
return (
<View style={styles.mainContainer}>

<ScrollView>
<View onLayout={this.setDropZoneValues.bind(this)}
style={[styles.dropZone , {marginTop : 10}]}>
</View>
<View onLayout={this.setDropZoneValues.bind(this)}
style={[styles.dropZone , {marginTop : 10}]}>
</View>
<View onLayout={this.setDropZoneValues.bind(this)}
style={[styles.dropZone , {marginTop : 10}]}>
</View>

{this.state.dataDragged.map((d, index) => (
<Animated.View
key={d-1}
style={[styles.draggableContainer, this.pan[d-1].getLayout(), styles.circle]}>
<Text style={styles.text}>Drag {d-1}</Text>
</Animated.View>
))}

</ScrollView>

{this.state.dataDrag.map((d, index) => (
<Animated.View
key={d-1}
{...this.getPanResponder(d-1).panHandlers}
style={[styles.draggableContainer, this.pan[d-1].getLayout(), styles.circle]}>
<Text style={styles.text}>Drag {d-1}</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
},
});

结果:

enter image description here

关于reactjs - 如何将拖动 View 绑定(bind)到ScrollView项目中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47566739/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com