SwiftUI:将视图与VStack中另一个视图的前端和后端对齐

时间:2019-08-22 02:53:30

标签: ios layout alignment swiftui

如何在SwiftUI VStack中将内容与另一个视图的前缘和后缘对齐?

我目前有以下SwiftUI代码:

struct MyBlock: View {
    var body: some View {
        Rectangle().foregroundColor(.gray).frame(width: 80, height: 80)
    }
}

struct MyGridView: View {
    var body: some View {
        HStack(spacing: 16) {
            MyBlock()
            MyBlock()
            MyBlock()
        }                       
    }
}

struct PinPad: View {
    var body: some View {
        VStack {
            MyGridView()
            HStack {
                Button(action: {}, label: { Text("Left Align") })
                Spacer()
                Button(action: {}, label: { Text("Right Align") })
            }
        }
    }
}

结果呈现如下:

Spacer consumes all the available space

但是我真正想要的是让"Left Align" ButtonMyGridView的左/前边缘对齐,并使"Right Align" ButtonMyGridView的右/后沿。

例如,像这样:

Aligned Buttons

我显然在这里缺少了一些非常基本的东西,因为在UIKit中使用自动布局很简单。

3 个答案:

答案 0 :(得分:8)

解决布局问题的第一件事是在视图上添加边框。这将使您看到视图的真实(和不可见)范围。问题将变得更加明显:

enter image description here

根据您的情况,可以通过将其全部包装在HStack中并添加一些垫片轻松地对其进行修复:

enter image description here

struct PinPad: View {
    var body: some View {
        HStack {
            Spacer()
            VStack {
                MyGridView().border(Color.blue, width: 3)
                HStack {
                    Button(action: {}, label: { Text("Left Align") }).border(Color.red, width: 3)
                    Spacer()
                    Button(action: {}, label: { Text("Right Align") }).border(Color.red, width: 3)
                }
            }.border(Color.green, width: 3)
            Spacer()
        }
    }
}

答案 1 :(得分:1)

GeometryReader是一个视图,可让您访问父级的大小和位置

定义了一个名为GeometryGetter的视图,

struct GeometryGetter: View {

    @Binding var rect: CGRect

    var body: some View {
        return GeometryReader { geometry in
            self.makeView(geometry: geometry)
        }
    }

    func makeView(geometry: GeometryProxy) -> some View {
        DispatchQueue.main.async {
            self.rect = geometry.frame(in: .global)
        }

        return Rectangle().fill(Color.clear)
    }
}

然后如下更改代码,

struct PinPad: View {

    @State private var rect: CGRect = CGRect()

    var body: some View {
        HStack {
            VStack {
                MyGridView().background(GeometryGetter(rect: $rect))
                HStack {
                    Button(action: {}, label: { Text("Left Align") })
                    Spacer()
                    Button(action: {}, label: { Text("Right Align") })
                }.frame(width: rect.width)
            }
        }
    }
}

答案 2 :(得分:0)

您可以在VStack之后添加.fixedSize()。