I've searched online for solutions but haven't found a clear example or tutorial that fits my requirements. Can someone provide guidance on how to achieve this? Any libraries or approaches that can simplify the implementation would be greatly appreciated.
I need to implement drag and drop functionality between two FlatLists. Specifically, I have two FlatLists displaying different sets of items, and I want the user to be able to drag an item from one FlatList and drop it into the other.
You can use React Native DraxList and DraxView also GestureHandlerRootView Install with npm :
npm i react-native-drax
npm install react-native-gesture-handler
Example:
import { Image, StatusBar, StyleSheet, Text, TouchableOpacity, View,
Dimensions, FlatList, ScrollView } from "react-native";
import React, { useState } from 'react';
import { Colors } from "../colors";
import { useNavigation } from "@react-navigation/native";
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { DraxProvider, DraxView, DraxList } from 'react-native-drax';
const Home = () => {
const draggableItemList = [
{
"id": 1,
"name": "EMI Calculators",
"logo_url": "../images/2.png"
},
{
"id": 2,
"name": "EMI Calculators",
"logo_url": "../images/2.png"
},
{
"id": 3,
"name": "EMI Calculators",
"logo_url": "../images/2.png"
},
{
"id": 4,
"name": "EMI Calculators",
"logo_url": "../images/2.png"
},
{
"id": 5,
"name": "EMI Calculators",
"logo_url": "../images/2.png"
},
];
const FirstReceivingItemList = [
{
"id": 5,
"name": "EMI Calculators",
"logo_url": "../images/2.png"
},
{
"id": 6,
"name": "EMI Calculators",
"logo_url": "../images/2.png"
},
{
"id": 7,
"name": "EMI Calculators",
"logo_url": "../images/2.png"
},
{
"id": 8,
"name": "EMI Calculators",
"logo_url": "../images/2.png"
},
];
const [receivingItemList, setReceivedItemList] = React.useState(FirstReceivingItemList);
const [dragItemMiddleList, setDragItemListMiddle] = React.useState(draggableItemList);
const navigation = useNavigation();
const DragUIComponent = ({ item, index }) => {
return (
<DraxView
style={[styles.centeredContent, styles.draggableBox]}
draggingStyle={styles.dragging}
dragReleasedStyle={styles.dragging}
hoverDraggingStyle={styles.hoverDragging}
dragPayload={index}
longPressDelay={150}
key={index}
receivingStyle={styles.receiving}
renderContent={({ viewState }) => {
return (
<View style={{
alignItems: 'center',
}}>
<TouchableOpacity style={[styles.profileImgContainer, { backgroundColor: Colors.black }]} >
<Image source={require('../images/2.png')} style={styles.profileImg} />
</TouchableOpacity>
<Text style={styles.text1}>{item.name}
</Text>
</View>
);
}}
>
</DraxView>
);
}
const ReceivingZoneUIComponent = ({ item, index }) => {
return (
<DraxView
style={[styles.centeredContent, styles.receivingZone]}
dragPayload={index}
receivingStyle={styles.receiving}
renderContent={({ viewState }) => {
// const receivingDrag = viewState && viewState.receivingDrag;
// const payload = receivingDrag && receivingDrag.payload;
return (
<View style={{
alignItems: 'center',
}}>
<TouchableOpacity style={[styles.profileImgContainer, { backgroundColor: Colors.black }]} >
<Image source={require('../images/2.png')} style={styles.profileImg} />
</TouchableOpacity>
<Text style={styles.text1}>{item.name}
</Text>
</View>
);
}}
key={index}
/>
);
}
const FlatListItemSeparator = () => {
return (<View style={styles.itemSeparator} />);
}
return (
<View style={styles.container}>
<GestureHandlerRootView
style={{ flex: 1 }}>
<DraxProvider>
{/* <ScrollView> */}
<View style={[styles.receivingContainer, {}]}>
<DraxView style={styles.innerLayout}
onReceiveDragDrop={(event) => {
console.log(event.dragged.payload)
let selected_item = dragItemMiddleList[event.dragged.payload];
let newReceivingItemList = [...receivingItemList];
newReceivingItemList[newReceivingItemList.length] = selected_item;
setReceivedItemList(newReceivingItemList);
const newDragItemMiddleList = [...dragItemMiddleList].filter((item) => item.id !== selected_item.id);
console.log(newDragItemMiddleList)
setDragItemListMiddle(newDragItemMiddleList);
}}>
<Text style={styles.headerText}>EMI Calculators</Text>
<DraxList
data={receivingItemList}
renderItemContent={ReceivingZoneUIComponent}
keyExtractor={(item, index) => {index.toString()}}
ItemSeparatorComponent={FlatListItemSeparator}
numColumns={4}
scrollEnabled={true}
/>
</DraxView>
</View>
<DraxView style={styles.innerLayout}
onReceiveDragDrop={(event) => {
console.log(event.dragged.payload)
console.log(receivingItemList)
let selected_item = receivingItemList[event.dragged.payload];
console.log(selected_item)
let newReceivingItemList = [...dragItemMiddleList];
newReceivingItemList[newReceivingItemList.length] = selected_item;
setDragItemListMiddle(newReceivingItemList);
const newDragItemMiddleList = [...receivingItemList].filter((item) => item.id !== selected_item.id);
console.log(newDragItemMiddleList)
setReceivedItemList(newDragItemMiddleList);
}}
>
<Text style={styles.headerText}>Loan</Text>
<View style={styles.draxListContainer}>
<DraxList
data={dragItemMiddleList}
renderItemContent={DragUIComponent}
keyExtractor={(item, index) => index.toString()}
numColumns={4}
ItemSeparatorComponent={FlatListItemSeparator}
scrollEnabled={true}
/>
</View>
</DraxView>
</DraxProvider>
</GestureHandlerRootView>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: Colors.backGroundColor,
},
innerLayout: {
marginHorizontal: 10,
paddingHorizontal:10,
marginVertical: 5,
borderRadius: 5,
backgroundColor: Colors.innerBackGroundColor,
borderColor: Colors.borderColor,
borderWidth: 1,
},
innerLayout1: {
marginStart: 10,
marginVertical: 5,
borderRadius: 5,
backgroundColor: Colors.innerBackGroundColor,
borderColor: Colors.borderColor,
borderWidth: 1,
flex: 1,
padding: 10,
},
innerLayout2: {
marginHorizontal: 10,
marginVertical: 5,
borderRadius: 5,
borderColor: Colors.borderColor,
borderWidth: 1,
flex: 1,
padding: 10,
},
headerText: {
fontFamily: 'groww_sans_medium',
fontSize: 20,
color: Colors.white,
marginVertical: 10,
},
text: {
fontSize: 10,
color: Colors.white,
marginTop: 5,
marginBottom: 10,
textAlign: 'center',
fontFamily: 'groww_sans_ragular'
},
text1: {
fontSize: 10,
color: Colors.white,
marginTop: 5,
textAlign: 'center',
fontFamily: 'groww_sans_ragular'
},
profileImgContainer: {
height: 35,
width: 35,
justifyContent: 'center',
alignItems: 'center',
borderRadius: 10,
backgroundColor: Colors.white
},
profileImg: {
height: 35,
width: 35,
borderRadius: 10,
},
leftContainer: {
justifyContent: 'flex-start',
flexDirection: 'row',
alignItems: 'center',
marginStart: 10
},
rightContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-end',
alignItems: 'center',
marginEnd: 10
},
receivingZone: {
height: (Dimensions.get('window').width / 4) - 12,
borderRadius: 10,
width: (Dimensions.get('window').width / 4) - 12,
justifyContent: 'center',
alignItems: 'center',
marginRight: 5
},
draggableBox: {
width: (Dimensions.get('window').width / 4) - 12,
height: (Dimensions.get('window').width / 4) - 12,
borderRadius: 10,
justifyContent: 'center',
alignItems: 'center',
marginRight: 5
},
});
export default Home;