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 })
}
})
}