gpt4 book ai didi

ios - SwiftUI |使用 onDrag 和 onDrop 在一个 LazyGrid 中重新排序项目?

转载 作者:行者123 更新时间:2023-12-01 15:19:50 35 4
gpt4 key购买 nike

我想知道是否可以使用 View.onDragView.onDrop在一个 LazyGrid 中添加拖放重新排序手动?
虽然我能够使用 onDrag 使每个项目都可拖动,我不知道如何实现丢弃部分。

这是我正在试验的代码:

import SwiftUI

//MARK: - Data

struct Data: Identifiable {
let id: Int
}

//MARK: - Model

class Model: ObservableObject {
@Published var data: [Data]

let columns = [
GridItem(.fixed(160)),
GridItem(.fixed(160))
]

init() {
data = Array<Data>(repeating: Data(id: 0), count: 100)
for i in 0..<data.count {
data[i] = Data(id: i)
}
}
}

//MARK: - Grid

struct ContentView: View {
@StateObject private var model = Model()

var body: some View {
ScrollView {
LazyVGrid(columns: model.columns, spacing: 32) {
ForEach(model.data) { d in
ItemView(d: d)
.id(d.id)
.frame(width: 160, height: 240)
.background(Color.green)
.onDrag { return NSItemProvider(object: String(d.id) as NSString) }
}
}
}
}
}

//MARK: - GridItem

struct ItemView: View {
var d: Data

var body: some View {
VStack {
Text(String(d.id))
.font(.headline)
.foregroundColor(.white)
}
}
}
谢谢!

最佳答案

SwiftUI 2.0
这是可能方法的完整简单演示(没有对其进行太多调整,因为代码增长速度与演示一样快)。
demo
要点是: a) 重新排序不假设等待丢弃,因此应动态跟踪; b)为了避免与坐标跳舞,处理网格项目 View 的拖放更简单; c) 在数据模型中找到要移动的内容并执行此操作,因此 SwiftUI 会自行为 View 设置动画。
使用 Xcode 12b3/iOS 14 测试

import SwiftUI
import UniformTypeIdentifiers

struct GridData: Identifiable, Equatable {
let id: Int
}

//MARK: - Model

class Model: ObservableObject {
@Published var data: [GridData]

let columns = [
GridItem(.fixed(160)),
GridItem(.fixed(160))
]

init() {
data = Array(repeating: GridData(id: 0), count: 100)
for i in 0..<data.count {
data[i] = GridData(id: i)
}
}
}

//MARK: - Grid

struct DemoDragRelocateView: View {
@StateObject private var model = Model()

@State private var dragging: GridData?

var body: some View {
ScrollView {
LazyVGrid(columns: model.columns, spacing: 32) {
ForEach(model.data) { d in
GridItemView(d: d)
.overlay(dragging?.id == d.id ? Color.white.opacity(0.8) : Color.clear)
.onDrag {
self.dragging = d
return NSItemProvider(object: String(d.id) as NSString)
}
.onDrop(of: [UTType.text], delegate: DragRelocateDelegate(item: d, listData: $model.data, current: $dragging))
}
}.animation(.default, value: model.data)
}
}
}

struct DragRelocateDelegate: DropDelegate {
let item: GridData
@Binding var listData: [GridData]
@Binding var current: GridData?

func dropEntered(info: DropInfo) {
if item != current {
let from = listData.firstIndex(of: current!)!
let to = listData.firstIndex(of: item)!
if listData[to].id != current!.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.current = nil
return true
}
}

//MARK: - GridItem

struct GridItemView: View {
var d: GridData

var body: some View {
VStack {
Text(String(d.id))
.font(.headline)
.foregroundColor(.white)
}
.frame(width: 160, height: 240)
.background(Color.green)
}
}
编辑
以下是如何在拖放到任何网格项目之外时修复永不消失的拖动项目:
struct DropOutsideDelegate: DropDelegate { 
@Binding var current: GridData?

func performDrop(info: DropInfo) -> Bool {
current = nil
return true
}
}
struct DemoDragRelocateView: View {
...

var body: some View {
ScrollView {
...
}
.onDrop(of: [UTType.text], delegate: DropOutsideDelegate(current: $dragging))
}
}
backup

关于ios - SwiftUI |使用 onDrag 和 onDrop 在一个 LazyGrid 中重新排序项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62606907/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com