检索列表视图项的矩形



是否有可能在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)
}
}

最新更新