我一直想知道在preview image
中使用onDrag
时是否有任何方法可以自定义要拖动的项目的LazyGrid
?
您可能会看到,preview image
保持不变,而所有其他项目都会改变其高度。
我也希望它的高度也较小。
像这样:
由于在拖动过程的开始就生成了该视图的渲染并将其用作preview image
,因此在设置项目高度之前 ,我不知道如何人们会意识到这一点。
一个想法是在LongPressGesture
手势之前先插入onDrag
。这样,我们可以在onDrag
开始之前设置高度,这将产生新高度的快照。我面临的问题是将这些手势组合在一起,使其功能像一个手势一样,而无需在它们之间释放。
也许还有另一种方法,或者我误解了某些东西?
这是完整的演示代码:
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 ContentView: View {
@StateObject private var model = Model()
@State private var dragging: GridData?
@State private var onDrag = false
var body: some View {
ScrollView {
LazyVGrid(columns: model.columns, spacing: 32) {
ForEach(model.data) { d in
GridItemView(d: d, onDrag: $onDrag)
.overlay(dragging?.id == d.id ? Color.white.opacity(0.8) : Color.clear)
.onDrag {
self.onDrag = true
self.dragging = d
return NSItemProvider(object: String(d.id) as NSString)
}
.onDrop(of: [UTType.text], delegate: DragRelocateDelegate(item: d, listData: $model.data, current: $dragging, onDrag: $onDrag))
}
}
.animation(.easeInOut(duration: 0.3), value: model.data)
}
}
}
//MARK: - Drag and Drop
struct DragRelocateDelegate: DropDelegate {
let item: GridData
@Binding var listData: [GridData]
@Binding var current: GridData?
@Binding var onDrag: Bool
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.onDrag = false
self.current = nil
return true
}
}
//MARK: - GridItem
struct GridItemView: View {
var d: GridData
@Binding var onDrag: Bool
var body: some View {
VStack {
Text(String(d.id))
.font(.headline)
.foregroundColor(.white)
}
.frame(width: 160, height: onDrag ? 140 : 240)
.background(Color.green)
.animation(.easeInOut(duration: 0.6))
}
}
谢谢!