如何使用 GeometryReader 在 LazyVGrid 中拖动视图?
How to drag across Views in a LazyVGrid with GeometryReader?
我想拖过网格中的矩形并更改它们的颜色。这段代码几乎可以正常工作,但这并不总是反应正确的矩形:它的行为相当随机。有什么提示吗?
import SwiftUI
struct ContentView: View {
let data = (0...3)
@State private var colors: [Color] = Array(repeating: Color.gray, count: 4)
@State private var rect = [CGRect]()
var columns: [GridItem] =
Array(repeating: .init(.fixed(70), spacing: 1), count: 2)
var body: some View {
LazyVGrid(columns: columns, spacing: 1) {
ForEach(data, id: \.self) { item in
Rectangle()
.fill(colors[item])
.frame(width: 70, height: 70)
.overlay(
GeometryReader{ geo in
Color.clear
.onAppear {
rect.insert(geo.frame(in: .global), at: rect.endIndex)
}
}
)
}
}
.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .global)
.onChanged({ (value) in
if let match = rect.firstIndex(where: { [=10=].contains(value.location) }) {
colors[match] = Color.red
}
})
)
}
}
如果我正确理解了您的目标,这里是固定变体(进行小的修改以避免重复硬编码)。
测试 Xcode 12.1 / iOS 14.1
struct ContentView: View {
let data = (0...3)
@State private var colors: [Color]
@State private var rect: [CGRect]
init() {
_colors = State(initialValue: Array(repeating: .gray, count: data.count))
_rect = State(initialValue: Array(repeating: .zero, count: data.count))
}
var columns: [GridItem] =
Array(repeating: .init(.fixed(70), spacing: 1), count: 2)
var body: some View {
LazyVGrid(columns: columns, spacing: 1) {
ForEach(data, id: \.self) { item in
Rectangle()
.fill(colors[item])
.frame(width: 70, height: 70)
.overlay(
GeometryReader{ geo in
Color.clear
.onAppear {
rect[item] = geo.frame(in: .global)
}
}
)
}
}
.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .global)
.onChanged({ (value) in
if let match = rect.firstIndex(where: { [=10=].contains(value.location) }) {
colors[match] = Color.red
}
})
)
}
}
我想拖过网格中的矩形并更改它们的颜色。这段代码几乎可以正常工作,但这并不总是反应正确的矩形:它的行为相当随机。有什么提示吗?
import SwiftUI
struct ContentView: View {
let data = (0...3)
@State private var colors: [Color] = Array(repeating: Color.gray, count: 4)
@State private var rect = [CGRect]()
var columns: [GridItem] =
Array(repeating: .init(.fixed(70), spacing: 1), count: 2)
var body: some View {
LazyVGrid(columns: columns, spacing: 1) {
ForEach(data, id: \.self) { item in
Rectangle()
.fill(colors[item])
.frame(width: 70, height: 70)
.overlay(
GeometryReader{ geo in
Color.clear
.onAppear {
rect.insert(geo.frame(in: .global), at: rect.endIndex)
}
}
)
}
}
.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .global)
.onChanged({ (value) in
if let match = rect.firstIndex(where: { [=10=].contains(value.location) }) {
colors[match] = Color.red
}
})
)
}
}
如果我正确理解了您的目标,这里是固定变体(进行小的修改以避免重复硬编码)。
测试 Xcode 12.1 / iOS 14.1
struct ContentView: View {
let data = (0...3)
@State private var colors: [Color]
@State private var rect: [CGRect]
init() {
_colors = State(initialValue: Array(repeating: .gray, count: data.count))
_rect = State(initialValue: Array(repeating: .zero, count: data.count))
}
var columns: [GridItem] =
Array(repeating: .init(.fixed(70), spacing: 1), count: 2)
var body: some View {
LazyVGrid(columns: columns, spacing: 1) {
ForEach(data, id: \.self) { item in
Rectangle()
.fill(colors[item])
.frame(width: 70, height: 70)
.overlay(
GeometryReader{ geo in
Color.clear
.onAppear {
rect[item] = geo.frame(in: .global)
}
}
)
}
}
.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .global)
.onChanged({ (value) in
if let match = rect.firstIndex(where: { [=10=].contains(value.location) }) {
colors[match] = Color.red
}
})
)
}
}