简体   繁体   English

在 swiftui 中拖放列表行

[英]Drag and drop on a List row in swiftui

I have been trying to implement drag and drop on a List in SwiftUI.我一直在尝试在 SwiftUI 中的List上实现拖放。 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 Remainders app on iOS .我想要做的是在List上拖动一行并将其放在 SAME List的一行上,就像iOS上的 Remainders 应用程序一样。

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.删除Text有效。

在此处输入图片说明

Dropping on the list row fails.删除列表行失败。

在此处输入图片说明

Hey unknown i may can help you.嘿未知我可以帮助你。

  1. Wrap your list into a navigationView将您的列表包装成一个导航视图
  2. You normally need an editing button, so you need an editMode var..您通常需要一个编辑按钮,因此您需要一个 editMode 变量。

So it should looks like this..所以它应该看起来像这样..

struct EditListView: View {
    @State private var items: [Item] = [
        Item(title: "Apple"),
        Item(title: "Banana"),
        Item(title: "Papaya"),
        Item(title: "Mango")
    ]
    @State private var editMode = EditMode.inactive

    var body: some View {
        NavigationView{
                VStack {
                    List {
                        ForEach(items) { item in
                        Text(item.title)
                        }
}                        
                    Text("Drop Item Here..")
                        .fontWeight(.heavy) 
                        .onDrop(of: [UTType.text], delegate:dropDelegate() )//works
                }
            }.environment(\.editMode,$editMode)
        }
    private var addButton : some View {
        switch editMode {
            case .inactive: 
                return AnyView(Button(action: onAdd) {Image(systemName: "plus")})
                default: 
            return AnyView(EmptyView())
        }
    }
}
  1. Now you want to add, delete and move items.现在您要添加、删除和移动项目。 So add the following functions to your struct因此,将以下函数添加到您的结构中

    func onAdd(){ items.append(Item(title: "Item \\(Self.count)")) } func onDelete(offsets: IndexSet) { items.remove(atOffsets: offsets) } func onMove(source: IndexSet, destination: Int) { items.move(fromOffsets: source, toOffset: destination) }

This should work :)这应该有效:)

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.第一:网络上的很多文章都报告说,该拖放不适用于 List 组件,但您可以将 List 替换为 ScrollView。 Then the drop method will be called.然后将调用 drop 方法。

Second : If you want to apply an action drop by item you have to move you drop method inside the foreach.第二:如果你想逐项应用一个动作,你必须在 foreach 中移动你的 drop 方法。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM