拖放列表以在 SwiftUI 上重新排序

Mat*_*uez 12 swiftui

如何在 SwiftUI 上添加拖放以重新排序行?只是一个没有“编辑模式”的干净解决方案。这里有一个例子:

在此处输入图片说明

更新

我在The SwiftUI Lab上问了这个问题,作者用这段代码回答了这个问题。仅适用于 iPad

    import SwiftUI

    struct Fruit: Identifiable {
        let id = UUID()
        let name: String
        let image: String
    }
            struct ContentView: View {
            @State var selection: Set<UUID> = []

            @State private var fruits = [
                Fruit(name: "Apple", image: "apple"),
                Fruit(name: "Banana", image: "banana"),
                Fruit(name: "Grapes", image: "grapes"),
                Fruit(name: "Peach", image: "peach"),
                Fruit(name: "Kiwi", image: "kiwi"),
            ]

            var body: some View {

                VStack {
                    NavigationView {
                        List(selection: $selection) {
                            ForEach(fruits) { fruit in
                                HStack {
                                    Image(fruit.image)
                                        .resizable()
                                        .frame(width: 30, height: 30)

                                    Text(fruit.name)
                                }
                            }
                            .onMove { _, _ in }
                        }
                        .navigationBarTitle("Fruits (Top)")
                    }
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)

小智 20

SwiftUI 列表中可拖动项目并更改顺序

当我尝试拖动项目时,我用 return NSItemProvider() 解决了这个问题。以及标准的.onMove 函数。

如果我理解正确的话,我将获取一个行容器作为 NSObject (感谢初始化 NSItemProvider),并且 .OnMove 使我能够对列表中的项目重新排序。

我仍在学习中,可能会误解一些细微差别。一定有更好的解释。但它确实有效(我只在 ios 15 上测试过这个,因为我在我的项目中使用了 .background 属性)。

// View
List {
    ForEach(tasks) { task in
        HStack { // Container of a row
             NavigationLink {
                 Text("There will be an editing View")
             } label: {
                 TaskListRowView(task: task)
             }
        }
        .onDrag { // mean drag a row container
             return NSItemProvider()
        }
     }
     .onDelete(perform: deleteItems)
     .onMove(perform: move) 
}

// Function
func move(from source: IndexSet, to destination: Int) {
    tasks.move(fromOffsets: source, toOffset: destination )
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一个被严重低估的解决方案。我搜索的所有其他解决方案都让我实现了一种自定义拖放机制,该机制不像默认机制那样流畅。干杯! (2认同)

cod*_*nd1 12

要在用户长按某个项目时将列表置于编辑模式,您可以使用状态标志并相应地设置编辑环境值。重要的是要使标志更改动画化,以免看起来很奇怪。

struct ContentView: View {
    @State private var fruits = ["Apple", "Banana", "Mango"]
    @State private var isEditable = false

    var body: some View {
        List {
            ForEach(fruits, id: \.self) { user in
                Text(user)
            }
            .onMove(perform: move)
            .onLongPressGesture {
                withAnimation {
                    self.isEditable = true
                }
            }
        }
        .environment(\.editMode, isEditable ? .constant(.active) : .constant(.inactive))
    }

    func move(from source: IndexSet, to destination: Int) {
        fruits.move(fromOffsets: source, toOffset: destination)
        withAnimation {
            isEditable = false
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Pau*_*III -4

对此有一篇很棒的文章:https://www.hackingwithswift.com/quick-start/swiftui/how-to-let-users-move-rows-in-a-list

我不想直接在这里复制粘贴Paul 的代码,所以这是我自己编写的另一个示例,结构略有不同。

import SwiftUI

struct ReorderingView: View {

  @State private var items = Array((0...10))

  var body: some View {
    NavigationView {
      VStack {
        List {
          ForEach(items) { item in
              Text("\(item)")
          }.onMove { (source: IndexSet, destination: Int) -> Void in
            self.items.move(fromOffsets: source, toOffset: destination)
          }
        }
      }
      //.environment(\.editMode, .constant(.active)) // use this to keep it editable always
      .navigationBarItems(trailing: EditButton()) // can replace with the above
      .navigationBarTitle("Reorder")
    }
  }
}

struct ReorderingView_Previews: PreviewProvider {
  static var previews: some View {
    ReorderingView()
  }
}

extension Int: Identifiable { // Please don't use this in production
  public var id: Int { return self }
}
Run Code Online (Sandbox Code Playgroud)