0

以下是我观点的内容:

HStack {
    Banner(items: items)
        .layoutPriority(100)
                
    OptionalView()
}

我只想在视图OptionalView中显示项目后显示是否有最小宽度剩余。Banner

我可以使用GeometryReader,但由于它是一个推出视图,如果OptionalView不需要它,它会占用一些空间并将横幅项目推到左侧,因此它们不会居中。

HStack {
    Banner(items: items)
        .layoutPriority(100)
                
    GeometryReader { geometry in
        if geometry.size.width >= 70 {
            OptionalView()
        }
    }
}
4

2 回答 2

1

Update EmptyView 是一个辅助视图,它在声明树中占用空间,但不在屏幕上。这是一个使用滑块动态设置横幅中项目数量的示例。当超过阈值时, EmptyView 作为第二个成员换入。

struct HysteresisView: View {
        @State var count : CGFloat = 10
        let threshold : CGFloat = 125
        var rectangles = [BannerItem]()
        
        init() {
            (0..<10).forEach { n in
                let color = UIColor(hue: CGFloat.random(in: 0...1), saturation: 0.75, brightness: 0.75, alpha: 1)
                let width = CGFloat.random(in: 30...100)
                rectangles.append(BannerItem(id: n, color: Color(color), width: width))
            }
        }
        
        var body: some View {
            VStack {
                Slider(value: $count, in: 1...10, label: { Text("Show this many") })
                HStack {
                    ForEach(rectangles.filter({ $0.id < Int(count) }), id: \.id) { rectangle in
                        Rectangle().foregroundColor(rectangle.color).frame(width: rectangle.width, height: 30)
                    }
                    Spacer()
                    GeometryReader { geo in
                        HStack {
                            if geo.size.width > threshold {
                                Text("Optional View")
                            } else {
                                EmptyView()
                            }
                        }
                        .frame(width: threshold)
                        .background(Color.gray)
                    }
                }.frame(height: 25)
                Spacer()
            }
        }
        
        struct BannerItem {
            let id : Int
            let color : Color
            let width : CGFloat
        }
    }
于 2021-02-13T19:55:51.750 回答
0

答案是使用 SwiftUI 文档稀少的PreferenceKey协议。

看:

这是一个方便的视图修饰符,它返回任何视图的框架:

fileprivate struct IntrinsicFramePreferenceKey: PreferenceKey {
    static var defaultValue: CGRect = .zero
    static func reduce(value: inout CGRect, nextValue: () -> CGRect) {}
}

fileprivate struct IntrinsicFrame: ViewModifier {
    @Binding var frame: CGRect
    
    func body(content: Content) -> some View {
        content
            .background(GeometryReader { geometry in
                Color.clear
                    .preference(key: IntrinsicFramePreferenceKey.self, value: geometry.frame(in: .global))
            })
            .onPreferenceChange(IntrinsicFramePreferenceKey.self) { newFrame in
                frame = newFrame
            }
    }
}

extension View {
    func intrinsicFrame(_ frame: Binding<CGRect>) -> some View {
        self.modifier(IntrinsicFrame(frame: frame))
    }
}

用法:

struct MyView: View {
    @State private var frame = CGRect()

    var body: some View {
        Text("Hello")
            .intrinsicFrame($frame)
    }
}
于 2021-03-05T18:47:57.013 回答