SwiftUI - 列表多选移动/重新排序(适用于 Mac,但不适用于 iOS)

问题描述 投票:0回答:1

如何启用多选,然后使用 ForEach(在 SwiftUI 中)移动/重新排序列表中的选定项目?

我尝试了以下代码。在 Mac 上它工作得很好 - 它允许我选择多个项目,然后将它们全部拖到列表中的另一个位置。在 iOS 上,它允许我通过拖放移动单个项目,并允许我进入编辑模式来选择多个项目,但是当我尝试通过拖放移动所选项目时,它们可以被拖动,但它们可以不要被删除到列表中的其他位置:

struct ExampleListView: View {
    @State var items = ["Dave", "Tom", "Jeremy", "Luke", "Phil"]
    
    @State var selectedItems: Set<String> = .init()
    
    var body: some View {
        NavigationView {
            List(selection: $selectedItems) {
                ForEach(items, id: \.self) { item in
                    Text(item).tag(item)
                }.onMove(perform: move)
            }
            .navigationBarItems(trailing: EditButton())
        }
    }
    
    func move(from source: IndexSet, to destination: Int) {
        items.move(fromOffsets: source, toOffset: destination)
    }
}

编辑 - 此代码具有相同的行为:

struct ExampleListView: View {
    @State var items = ["Dave", "Tom", "Jeremy", "Luke", "Phil"]
    
    @State var selectedItems: Set<String> = .init()
    
    var body: some View {
        NavigationView {
            List($items, id: \.self, editActions: .all, selection: $selectedItems) { $item in
                Text(item).tag(item)
            }
            .navigationBarItems(trailing: EditButton())
        }
    }
    
    func move(from source: IndexSet, to destination: Int) {
        items.move(fromOffsets: source, toOffset: destination)
    }
}
ios swift swiftui drag-and-drop multi-select
1个回答
0
投票

实现此目的的一种方法是手动处理拖放交互。以下是如何修改代码以在 macOS 和 iOS 上启用多项目拖放功能

import SwiftUI

struct ExampleListView: View {
 @State var items = ["Dave", "Tom", "Jeremy", "Luke", "Phil"]

 @State var selectedItems: Set<String> = .init()
 @State var draggedItems: [String] = []

 var body: some View {
    NavigationView {
        List {
            ForEach(items, id: \.self) { item in
                Text(item)
                    .gesture(
                        DragGesture()
                            .onChanged { value in
                                if !self.selectedItems.contains(item) {
                                    self.selectedItems = [item]
                                }
                                self.draggedItems = Array(self.selectedItems)
                            }
                    )
                    .onDrag {
                        NSItemProvider(object: NSString(string: item))
                    }
                    .onDrop(of: [UTType.text], delegate: MyDropDelegate(item: item, listItems: $items, selectedItems: $selectedItems, draggedItems: $draggedItems))
            }
        }
        .navigationBarItems(trailing: EditButton())
        }
    }
}

struct MyDropDelegate: DropDelegate {
let item: String
@Binding var listItems: [String]
@Binding var selectedItems: Set<String>
@Binding var draggedItems: [String]

func performDrop(info: DropInfo) -> Bool {
    let destinationIndex = self.listItems.firstIndex(of: item) ?? 0
    var startIndex = 0
    
    for i in 0..<listItems.count {
        if draggedItems.contains(listItems[i]) {
            let item = listItems.remove(at: i)
            listItems.insert(item, at: destinationIndex + startIndex)
            startIndex += 1
        }
    }
    
    selectedItems = []
    draggedItems = []
    
    return true
  }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ExampleListView()
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.