Layout in SwiftUI with horizontal and vertical alignment

后端 未结 6 2073
别跟我提以往
别跟我提以往 2021-02-04 09:11

I\'m trying to accomplish this layout

If I try HStack wrapped in VStack, I get this:

If I try VStack wrapped in HStack, I get this:

6条回答
  •  栀梦
    栀梦 (楼主)
    2021-02-04 09:51

    You could use kontiki's geometry reader hack for this:

    struct Column: View {
        @State private var height: CGFloat = 0
        @State var text = ""
        let spacing: CGFloat = 8
    
        var body: some View {
            HStack {
                VStack(alignment: .leading, spacing: spacing) {
                    Group {
                        Text("Hello world")
                        Text("Hello Two")
                        Text("Hello Three")
                    }.frame(height: height)
                }.fixedSize(horizontal: true, vertical: false)
                VStack(spacing: spacing) {
                    TextField("label", text: $text).bindHeight(to: $height)
                    TextField("label 2", text: $text)
                    TextField("label 3", text: $text)
                }.textFieldStyle(RoundedBorderTextFieldStyle())
            }.fixedSize().padding()
        }
    }
    
    extension View {
        func bindHeight(to binding: Binding) -> some View {
            func spacer(with geometry: GeometryProxy) -> some View {
                DispatchQueue.main.async { binding.value = geometry.size.height }
                return Spacer()
            }
            return background(GeometryReader(content: spacer))
        }
    }
    

    We are only reading the height of the first TextField here and applying it three times on the three different Text Views, assuming that all TextFields have the same height. If your three TextFields have different heights or have appearing/disappearing verification labels that affect the individual heights, you can use the same technique but with three different height bindings instead.

    Why is this a bit of a hack?

    Because this solution will always first render the TextFields without the labels. During this render phase it will set the height of the Text labels and trigger another render. It would be more ideal to render everything in one layout phase.

提交回复
热议问题