【问题标题】:List with drag and drop to reorder on SwiftUI拖放列表以在 SwiftUI 上重新排序
【发布时间】:2019-06-27 11:59:21
【问题描述】:

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

更新

我在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)")
                    }
                }
            }
        }

【问题讨论】:

    标签: swiftui


    【解决方案1】:

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

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

    【讨论】:

    • 这是一个好的开始,但没有提供 OP 示例的行为。长按手势将启动编辑模式,但不会立即拖动当前长按行。
    【解决方案2】:

    Draggable items in SwiftUI List with changing the order

    当我尝试拖动一个项目时,我通过 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 )
    }
    

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 2012-05-08
        • 2012-05-31
        • 1970-01-01
        • 2012-06-19
        • 2022-07-12
        • 1970-01-01
        • 2020-04-05
        • 1970-01-01
        • 2010-12-28
        相关资源
        最近更新 更多