观察SwiftUI中的帧变化
我有一个可以在其他视图(比如说类别)上拖放的视图。为了检测我在哪个类别视图上,我将它们的帧存储在一个帧数组中,这发生在它们的不可见覆盖的外观上。(这是基于本教程中的Paul Hudsons实现) 这一切都很好,除非这些视图的位置发生变化,例如在设备方向或iPad上调整窗口大小时。这当然不会在出现时触发,因此帧不再匹配观察SwiftUI中的帧变化,swiftui,geometryreader,Swiftui,Geometryreader,我有一个可以在其他视图(比如说类别)上拖放的视图。为了检测我在哪个类别视图上,我将它们的帧存储在一个帧数组中,这发生在它们的不可见覆盖的外观上。(这是基于本教程中的Paul Hudsons实现) 这一切都很好,除非这些视图的位置发生变化,例如在设备方向或iPad上调整窗口大小时。这当然不会在出现时触发,因此帧不再匹配 HStack() { ForEach(categories) { category in ZStack { Circle() Rectang
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){categories in
ZStack{
圈()
矩形()
.foregroundColor(.clear)
.background(//不完全是,因为他们用UIKit实现了这一点,对我来说,UIKit不如纯SwiftUI理想。他们说用GeometryReader应该可以实现,但没有解释如何实现。
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
}
}
}