Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
观察SwiftUI中的帧变化_Swiftui_Geometryreader - Fatal编程技术网

观察SwiftUI中的帧变化

观察SwiftUI中的帧变化,swiftui,geometryreader,Swiftui,Geometryreader,我有一个可以在其他视图(比如说类别)上拖放的视图。为了检测我在哪个类别视图上,我将它们的帧存储在一个帧数组中,这发生在它们的不可见覆盖的外观上。(这是基于本教程中的Paul Hudsons实现) 这一切都很好,除非这些视图的位置发生变化,例如在设备方向或iPad上调整窗口大小时。这当然不会在出现时触发,因此帧不再匹配 HStack() { ForEach(categories) { category in ZStack { Circle() Rectang

我有一个可以在其他视图(比如说类别)上拖放的视图。为了检测我在哪个类别视图上,我将它们的帧存储在一个帧数组中,这发生在它们的不可见覆盖的外观上。(这是基于本教程中的Paul Hudsons实现)

这一切都很好,除非这些视图的位置发生变化,例如在设备方向或iPad上调整窗口大小时。这当然不会在出现时触发,因此帧不再匹配

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
        }
    }

}