使SwiftUI矩形的高度或宽度与另一个矩形相同

时间:2020-07-30 03:14:10

标签: swift macos swiftui

对于macOS应用中的SwiftUI布局,我具有三个矩形,如下所示:

layout 1

产生这种布局的代码是:

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            HStack {
                ZStack {
                    Rectangle()
                        .fill(Color.purple)
                        .frame(width: 20)
                    Text("1")
                        .font(.subheadline)
                        .foregroundColor(.white)
                }
                
                ZStack {
                    Rectangle()
                        .fill(Color.orange)
                    Text("2")
                        .font(.subheadline)
                        .foregroundColor(.white)
                }
            }
            
            HStack {                
                ZStack {
                    Rectangle()
                        .fill(Color.red)
                        .frame(height: 20)
                    Text("3")
                           .font(.subheadline)
                           .foregroundColor(.white)
                }
            }
        }
        .frame(minWidth: 400, minHeight: 250)
    }
}

我的目标是使Rectangle 1与Rectangle 2的高度相同,并使Rectangle 3与Rectangle 2的宽度相同。矩形之间的大小关系应随窗口大小的改变而保持不变。正确完成后,最终结果应如下所示:

layout 2

如何在SwiftUI中完成此操作?

1 个答案:

答案 0 :(得分:0)

这是一种基于视图首选项的有效方法。经过Xcode 11.4 / macOS 10.15.6的测试

demo

struct ViewWidthKey: PreferenceKey {
    typealias Value = CGFloat
    static var defaultValue: CGFloat { 0 }
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value = value + nextValue()
    }
}

struct ContentView: View {
    @State private var boxWidth = CGFloat.zero
    var body: some View {
        VStack {
            HStack {
                ZStack {
                    Rectangle()
                        .fill(Color.purple)
                        .frame(width: 20)
                    Text("1")
                        .font(.subheadline)
                        .foregroundColor(.white)
                }

                ZStack {
                    Rectangle()
                        .fill(Color.orange)
                    Text("2")
                        .font(.subheadline)
                        .foregroundColor(.white)
                }
                .background(GeometryReader {
                    Color.clear.preference(key: ViewWidthKey.self,
                        value: $0.frame(in: .local).size.width) })
            }

            HStack {
                ZStack {
                    Rectangle()
                        .fill(Color.red)
                        .frame(height: 20)
                    Text("3")
                           .font(.subheadline)
                           .foregroundColor(.white)
                }.frame(width: boxWidth)
            }.frame(maxWidth: .infinity, alignment: .bottomTrailing)
        }
        .onPreferenceChange(ViewWidthKey.self) { self.boxWidth = $0 }
        .frame(minWidth: 400, minHeight: 250)
    }
}