I have been trying to implement drag and drop on a List in SwiftUI. What I'm trying to do is drag a row on a List and drop it on a row in the SAME List, much like the Reminders app on iOS.
Note: It's important to note that I'm not trying to rearrange the list but rather make the dropped item a "child" of that row.
import SwiftUI
import UniformTypeIdentifiers
struct Item: Identifiable {
let id = UUID()
let title: String
}
struct EditListView: View {
@State private var items: [Item] = [
Item(title: "Apple"),
Item(title: "Banana"),
Item(title: "Papaya"),
Item(title: "Mango")
]
var body: some View {
VStack {
List {
ForEach(items) { item in
Text(item.title)
}
.onDrop(of: [UTType.text], delegate:dropDelegate() )//doesn't work
.onDrag{
NSItemProvider(item: .some(URL(string: "item")! as NSSecureCoding), typeIdentifier: String() )
}
}
Text("Drop Item Here..")
.fontWeight(.heavy)
.onDrop(of: [UTType.text], delegate:dropDelegate() )//works
}
}
}
class dropDelegate: DropDelegate {
func performDrop(info: DropInfo) -> Bool {
print("drop success")
return true
}
}
Dropping on the Text works.

Dropping on the list row fails.

It seems that there is two problems with your code.
First : many article on the web report that the drop is not working on List component, but you can replace the List by a ScrollView. Then the drop method will be called.
Second: If you want to apply an action drop by item you have to move you drop method inside the foreach.
In the updated code, I just added a sample cell, you can easily reproduce a cell effect by yourself :
struct Sample: View {
@State private var items: [Item] = [
Item(title: "Apple"),
Item(title: "Banana"),
Item(title: "Papaya"),
Item(title: "Mango")
]
var body: some View {
VStack {
ScrollView {
ForEach(items) { item in
SampleCell(item: item)
.onDrop(of: [UTType.text], delegate:dropDelegate() )
.onDrag{
NSItemProvider(item: .some(URL(string: "item")! as NSSecureCoding), typeIdentifier: String() )
}
}
}
Text("Drop Item Here..")
.fontWeight(.heavy)
.onDrop(of: [UTType.text], delegate:dropDelegate() )//works
}
}
}
struct SampleCell: View {
var item : Item
var body: some View {
HStack {
Text(item.title).padding()
Spacer()
}.frame(maxWidth:.infinity, minHeight: 60)
.background(Color.gray)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With