我有可以拖放到其他视图之上的视图(可以说类别)。为了检测我位于哪个类别视图上,我将其框架存储在frames数组中,这发生在其不可见叠加层的onAppear中。(这是基于本教程中的Paul Hudsons实现)。
除非这些视图的位置发生变化(例如在设备方向或iPad上调整窗口大小)时,这一切都很好。当然,这不会触发onAppear,因此框架不再匹配。
HStack() {
ForEach(categories) { category in
ZStack {
Circle()
Rectangle()
.foregroundColor(.clear)
.overlay(
GeometryReader { geo in
Color.clear
.onAppear {
categoryFrames[index(for: category)] = geo.frame(in: .global)
}
}
)
}
}
}
因此,欢迎有任何想法在这些情况下更新框架或如何以不同的方式观察它们。
可以在刷新期间使用视图首选项动态读取视图框架,因此您不必担心方向,因为每次重绘视图时都有实际的框架。
这是方法草案。
介绍视图偏好键的模型:
struct ItemRec: Equatable {
let i: Int // item index
let p: CGRect // item position frame
}
struct ItemPositionsKey: PreferenceKey {
typealias Value = [ItemRec]
static var defaultValue = Value()
static func reduce(value: inout Value, nextValue: () -> Value) {
value.append(contentsOf: nextValue())
}
}
现在是您的代码(假设@State private var categoryFrames = [Int, CGRect]()
)
HStack() {
ForEach(categories) { category in
ZStack {
Circle()
Rectangle()
.foregroundColor(.clear)
.background( // << prefer background to avoid any side effect
GeometryReader { geo in
Color.clear.preference(key: ItemPositionsKey.self,
value: [ItemRec(i: index(for: category), p: geo.frame(in: .global))])
}
)
}
}
.onPreferenceChange(ItemPositionsKey.self) {
// actually you can use this listener at any this view hierarchy level
// and possibly use directly w/o categoryFrames state
for item in $0 {
categoryFrames[item.i] = item.p
}
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句