如何将颜色从源拖放到目的地并保留它?我目前的代码可以临时执行此操作(从源拖动时更改目标的颜色),但在鼠标松开时它会很快变回原样。那么,如何才能使颜色更改保持在鼠标悬停在特定单元格上的状态,并且能够在将来将鼠标悬停在该特定单元格上拖动时再次更改该单元格呢?我当前的代码基于here https://stackoverflow.com/questions/58900316/draggesture-on-a-vstack-with-lot-of-buttons-how-to-detect-when-the-drag-is-insi.
import SwiftUI
struct ContentView: View {
var body: some View {
HStack {
ColorSource(color: .purple, color2: .orange)
Spacer()
ColorSource(color: .blue, color2: .pink)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
struct DestinationDataKey: PreferenceKey {
typealias Value = [DestinationData]
static var defaultValue: [DestinationData] = []
static func reduce(value: inout [DestinationData], nextValue: () -> [DestinationData]) {
value.append(contentsOf: nextValue())
}
}
struct DestinationData: Equatable {
let destination: Int
let frame: CGRect
}
struct DestinationDataSetter: View {
let destination: Int
var body: some View {
GeometryReader { geometry in
Rectangle()
.fill(Color.clear)
.preference(key: DestinationDataKey.self,
value: [DestinationData(destination: self.destination, frame: geometry.frame(in: .global))])
}
}
}
struct DestinationView: View {
@Binding var active: Int
let label: String
let id: Int
let color: Color
var body: some View {
Text(label).padding(10).background(self.active == id ? color : Color.green)
.background(DestinationDataSetter(destination: id))
}
}
struct ColorSource: View {
@State var active = 0
@State var destinations: [Int: CGRect] = [:]
@State var color:Color
@State var color2:Color
@State var draggingFirstColor:Bool = false
@State var draggingSecondColor:Bool = false
var body: some View {
VStack {
Text("Drag From Here").padding().background(color)
.gesture(DragGesture(minimumDistance: 0.1, coordinateSpace: .global)
.onChanged { value in
self.draggingFirstColor = true
self.active = 0
for (id, frame) in self.destinations {
if frame.contains(value.location) {
self.active = id
}
}
}
.onEnded { value in
// do something on drop
self.active = 0
self.draggingFirstColor = false
}
)
Text("Drag From Here").padding().background(color2)
.gesture(DragGesture(minimumDistance: 0.1, coordinateSpace: .global)
.onChanged { value in
self.draggingSecondColor = true
self.active = 0
for (id, frame) in self.destinations {
if frame.contains(value.location) {
self.active = id
}
}
}
.onEnded { value in
// do something on drop
self.active = 0
self.draggingSecondColor = false
}
)
Divider()
DestinationView(active: $active, label: "Drag Over Me", id: 1, color: (draggingFirstColor ? color : (draggingSecondColor ? color2 : Color.green)))
DestinationView(active: $active, label: "Drag Over Me", id: 2, color: (draggingFirstColor ? color : (draggingSecondColor ? color2 : Color.green)))
DestinationView(active: $active, label: "Drag Over Me", id: 3, color: (draggingFirstColor ? color : (draggingSecondColor ? color2 : Color.green)))
DestinationView(active: $active, label: "Drag Over Me", id: 4, color: (draggingFirstColor ? color : (draggingSecondColor ? color2 : Color.green)))
}.onPreferenceChange(DestinationDataKey.self) { preferences in
for p in preferences {
self.destinations[p.destination] = p.frame
}
}
}
}