是否有可能在onLongPressGesture
上获得列表项视图的CGRect
?
struct ContentView: View {
var body: some View {
ScrollView {
LazyVStack {
ForEach((1...10), id: .self) {
Text("($0)")
.frame(height: 80)
.frame(maxWidth: .infinity)
.background(.yellow)
.onLongPressGesture {
// here I need to use the rectangle
}
}
}
}
}
}
一种方法是为列表项视图创建一个单独的结构体,并在其中存储矩形的状态:
struct ItemView: View {
let value: Int
@State var rect: CGRect = .zero
var body: some View {
Text("(value)")
.frame(height: 80)
.frame(maxWidth: .infinity)
.background(.yellow)
.background(GeometryReader { gp in
Color.clear.onAppear{
rect = gp.frame(in: .global)
}
})
}
}
但不幸的是,在目前的实现这不是一个选项,我需要在列表视图中存储坐标。
使用PreferenceKey
工作(感谢@jnpdx的建议)。如果有人想知道如何做到这一点,这里是完整的实现:
struct ContentView: View {
@State var frames = [Int: CGRect]()
var body: some View {
ScrollView {
LazyVStack {
ForEach((1...10), id: .self) { itemID in
ItemView(value: itemID)
.modifier(FrameModifier())
.onLongPressGesture {
print(frames[itemID])
}
.onPreferenceChange(FramePreferenceKey.self) {
frames[itemID] = $0
}
}
}
}
}
}
struct ItemView: View {
let value: Int
var body: some View {
Text("(value)")
.frame(height: 80)
.frame(maxWidth: .infinity)
.background(.yellow)
}
}
struct FramePreferenceKey: PreferenceKey {
static var defaultValue: CGRect = .zero
static func reduce(value: inout CGRect, nextValue: () -> CGRect) {
value = nextValue()
}
}
struct FrameModifier: ViewModifier {
private var sizeView: some View {
GeometryReader { geometry in
Color.clear.preference(key: FramePreferenceKey.self, value: geometry.frame(in: .global))
}
}
func body(content: Content) -> some View {
content.background(sizeView)
}
}