如何在不切换 EditMode 的情况下移动列表项
How can I move List Items without having to toggle EditMode
我目前正在 SwiftUI 中构建一个待办事项列表应用程序。我真正想实现的一个功能是能够手动对您的列表进行排序,因此我在 ForEach
循环中使用 .onMove
修饰符集成了该功能以填充我的 List
,但我仍然必须手动切换 EditMode,所以我将列表的 EditMode 设置为 .active
,如下所示:
import SwiftUI
struct ContentView: View {
@State private var items = ["1", "2", "3"]
@State var editMode: EditMode = .active
var body: some View {
List {
ForEach(items, id: \.self) { item in
Text("Item \(item)")
}
.onMove(perform: { _, _ in })
}
.environment(\.editMode, $editMode)
}
}
但我对这个实现不满意,因为我仍然必须使用 EditMode 中的手柄,而且它还破坏了 SwipeActions 以及 Button 功能。
那么如何在不使用 EditMode 的情况下移动列表项?
根据 Asperi 对 问题的回答,我实施了拖放手势来解决该问题,如下所示:
struct ContentView: View {
@State var items = [Item(id: 1), Item(id: 2), Item(id: 3), Item(id: 4)]
@State private var dragging: Item?
var body: some View{
List{
ForEach(items){ item in
Text("Item \(item.id)")
.onDrag {
self.dragging = item
return NSItemProvider(object: NSString())
}
.onDrop(of: [UTType.text], delegate: DragDelegate(current: $dragging))
}
.onMove(perform: {_, _ in })
}
}
}
使用 DropDelegate
实现:
struct DragDelegate<Item: Equatable>: DropDelegate {
@Binding var current: Item?
func dropUpdated(info: DropInfo) -> DropProposal? {
DropProposal(operation: .move)
}
func performDrop(info: DropInfo) -> Bool {
current = nil
return true
}
}
注意:项目现在必须符合 Identifiable
& Equatable
所以最小的实现是:
struct Item: Identifiable, Equatable{
let id: Int
}
你还需要导入:
import UniformTypeIdentifiers
为了使用拖放功能
我目前正在 SwiftUI 中构建一个待办事项列表应用程序。我真正想实现的一个功能是能够手动对您的列表进行排序,因此我在 ForEach
循环中使用 .onMove
修饰符集成了该功能以填充我的 List
,但我仍然必须手动切换 EditMode,所以我将列表的 EditMode 设置为 .active
,如下所示:
import SwiftUI
struct ContentView: View {
@State private var items = ["1", "2", "3"]
@State var editMode: EditMode = .active
var body: some View {
List {
ForEach(items, id: \.self) { item in
Text("Item \(item)")
}
.onMove(perform: { _, _ in })
}
.environment(\.editMode, $editMode)
}
}
但我对这个实现不满意,因为我仍然必须使用 EditMode 中的手柄,而且它还破坏了 SwipeActions 以及 Button 功能。
那么如何在不使用 EditMode 的情况下移动列表项?
根据 Asperi 对
struct ContentView: View {
@State var items = [Item(id: 1), Item(id: 2), Item(id: 3), Item(id: 4)]
@State private var dragging: Item?
var body: some View{
List{
ForEach(items){ item in
Text("Item \(item.id)")
.onDrag {
self.dragging = item
return NSItemProvider(object: NSString())
}
.onDrop(of: [UTType.text], delegate: DragDelegate(current: $dragging))
}
.onMove(perform: {_, _ in })
}
}
}
使用 DropDelegate
实现:
struct DragDelegate<Item: Equatable>: DropDelegate {
@Binding var current: Item?
func dropUpdated(info: DropInfo) -> DropProposal? {
DropProposal(operation: .move)
}
func performDrop(info: DropInfo) -> Bool {
current = nil
return true
}
}
注意:项目现在必须符合 Identifiable
& Equatable
所以最小的实现是:
struct Item: Identifiable, Equatable{
let id: Int
}
你还需要导入:
import UniformTypeIdentifiers
为了使用拖放功能