Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drag and drop on a List row in swiftui

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.

enter image description here

Dropping on the list row fails.

enter image description here

like image 729
unknown Avatar asked Oct 29 '25 17:10

unknown


1 Answers

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)
    }
}
like image 130
Hikosei Avatar answered Oct 31 '25 09:10

Hikosei