来源: https://stackoverflow.com/questions/62606907/swiftui-using-ondrag-and-ondrop-to-reorder-items-within-one-single-lazygrid
本文主要使用到了onDrag
和onDrop
方法,此外还有类似的onInsert
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
import SwiftUI import UniformTypeIdentifiers
struct GridData: Identifiable, Equatable { let id: Int static func == (lhs: Self, rhs: Self) -> Bool { return lhs.id == rhs.id } }
func getData() -> [GridData] { var data: [GridData] = [] for i in 0..<100 { data.append(GridData(id: i)) } return data }
struct SwiftUIView: View { @State private var data = getData() @State private var draggingData: GridData? let columns: [GridItem] = [ GridItem(.flexible(minimum: 50, maximum: 200), spacing: 30), GridItem(.flexible(minimum: 50, maximum: 200), spacing: 30), GridItem(.flexible(minimum: 50, maximum: 200), spacing: 30), ] var body: some View { ScrollView { LazyVGrid(columns: columns, spacing: 30, content: { ForEach(data) { d in Text(d.id.description) .font(.headline) .foregroundColor(.white) .frame(width: 100, height: 100, alignment: .center) .background(Color.pink) .overlay(draggingData?.id == d.id ? Color.white.opacity(0.8) : Color.clear) .onDrag({ self.draggingData = d return NSItemProvider(object: d.id.description as NSString) }) .onDrop(of: [ UTType.text], delegate: DropRelocateDelegate(item: d, listData: $data, currentData: $draggingData)) } }) } .onDrop(of: [UTType.text], delegate: DropOutsideDelegate(currentData: $draggingData)) .animation(.easeInOut) .padding() .background(Color.black) .edgesIgnoringSafeArea(.bottom) } }
struct DropOutsideDelegate: DropDelegate { @Binding var currentData: GridData? func performDrop(info: DropInfo) -> Bool { currentData = nil return true } }
struct DropRelocateDelegate: DropDelegate { let item: GridData @Binding var listData: [GridData] @Binding var currentData: GridData? func dropEntered(info: DropInfo) { if item != currentData { let from = listData.firstIndex(of: currentData!)! let to = listData.firstIndex(of: item)! if listData[to].id != currentData!.id { listData.move(fromOffsets: IndexSet(integer: from), toOffset: to > from ? to + 1: to) } } } func dropUpdated(info: DropInfo) -> DropProposal? { return DropProposal(operation: .move) } func performDrop(info: DropInfo) -> Bool { self.currentData = nil return true } }
struct SwiftUIView_Previews: PreviewProvider { static var previews: some View { SwiftUIView() } }
|
参考:
https://swiftui-lab.com/drag-drop-with-swiftui/
https://swiftwithmajid.com/2020/04/01/drag-and-drop-in-swiftui/