在 SwiftUI 中制作宽度和高度相同的按钮网格

Make a grid of buttons of same width and height in SwiftUI

我正在尝试使用 SwiftUI 创建一个计算器,我现在正在努力创建按钮网格以水平填充可用 space

现在我只是想让按钮填充 3 x 3 等高和等宽的网格

我可以根据 使用 Spacer() 使它们具有相同的高度,但相同的宽度是我现在卡住的地方:

import SwiftUI

struct ContentView : View {
    var body: some View {
        VStack(alignment: .center, spacing: 50) {
            HStack(alignment: .center, spacing: 50) {
                Button(action: {}) {
                    Text("7")
                    Spacer()
                }.background(Color.green)
                Button(action: {}) {
                    Text("8")
                    Spacer()
                }.background(Color.yellow)
                Button(action: {}) {
                    Text("9")
                    Spacer()
                }.background(Color.green)
            }
            HStack(alignment: .center, spacing: 50) {
                Button(action: {}) {
                    Text("4")
                    Spacer()
                }.background(Color.yellow)
                Button(action: {}) {
                    Text("5")
                    Spacer()
                }.background(Color.green)
                Button(action: {}) {
                    Text("6")
                    Spacer()
                }.background(Color.yellow)
            }
            HStack(alignment: .center, spacing: 50) {
                Button(action: {}) {
                    Text("1")
                    Spacer()
                }.background(Color.green)
                Button(action: {}) {
                    Text("2")
                    Spacer()
                }.background(Color.yellow)
                Button(action: {}) {
                    Text("3")
                    Spacer()
                }.background(Color.green)
            }
        }.aspectRatio(contentMode: .fill)
    }
}

#if DEBUG
struct ContentView_Previews : PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

这是我当前的输出与我想要的所需输出的示例。首先,我尝试让按钮填充当前区域,稍后我将尝试让 0 按钮填充 2 个单元格。

使用 GeometryReader(docs here) 怎么样?他们将父视图的维度提供给子视图。这是基于您已有的部分实现:

import SwiftUI

struct ContentView : View {
    var body: some View {
        VStack {
            Text("0")
            NumpadView()
        }
    }
}

struct NumpadView : View {

    let rows: Length = 5
    let columns: Length = 4
    let spacing: Length = 10

    var horizontalEdges: Length {
        return columns - 1
    }

    var verticalEdges: Length {
        return rows - 1
    }

    func getItemWidth(containerWidth: Length) -> Length {
        return (containerWidth - spacing * horizontalEdges) / columns
    }

    func getItemHeight(containerHeight: Length) -> Length {
        return (containerHeight - spacing * verticalEdges) / rows
    }

    var body: some View {
        GeometryReader { geometry in

        VStack(alignment: .center, spacing: self.spacing) {
            HStack(alignment: .center, spacing: self.spacing) {
                Button(action: {}) {
                    Text("7")
                        .frame(width: self.getItemWidth(containerWidth: geometry.size.width), height: self.getItemHeight(containerHeight: geometry.size.height))
                        .background(Color.green)
                    }

                Button(action: {}) {
                    Text("8")
                        .frame(width: self.getItemWidth(containerWidth: geometry.size.width), height: self.getItemHeight(containerHeight: geometry.size.height))
                        .background(Color.yellow)
                    }

                Button(action: {}) {
                    Text("9")
                        .frame(width: self.getItemWidth(containerWidth: geometry.size.width), height: self.getItemHeight(containerHeight: geometry.size.height))
                        .background(Color.green)
                    }
                }

            HStack(alignment: .center, spacing: self.spacing) {
                Button(action: {}) {
                    Text("4")
                        .frame(width: self.getItemWidth(containerWidth: geometry.size.width), height: self.getItemHeight(containerHeight: geometry.size.height))
                        .background(Color.yellow)
                }

                Button(action: {}) {
                    Text("5")
                        .frame(width: self.getItemWidth(containerWidth: geometry.size.width), height: self.getItemHeight(containerHeight: geometry.size.height))
                        .background(Color.green)
                }

                Button(action: {}) {
                    Text("6")
                        .frame(width: self.getItemWidth(containerWidth: geometry.size.width), height: self.getItemHeight(containerHeight: geometry.size.height))
                        .background(Color.yellow)
                }
            }

            HStack(alignment: .center, spacing: self.spacing) {
                Button(action: {}) {
                    Text("1")
                        .frame(width: self.getItemWidth(containerWidth: geometry.size.width), height: self.getItemHeight(containerHeight: geometry.size.height))
                        .background(Color.green)
                }

                Button(action: {}) {
                    Text("2")
                        .frame(width: self.getItemWidth(containerWidth: geometry.size.width), height: self.getItemHeight(containerHeight: geometry.size.height))
                        .background(Color.yellow)
                }

                Button(action: {}) {
                    Text("3")
                        .frame(width: self.getItemWidth(containerWidth: geometry.size.width), height: self.getItemHeight(containerHeight: geometry.size.height))
                        .background(Color.green)
                }
            }

            HStack(alignment: .center, spacing: self.spacing) {
                Button(action: {}) {
                    Text("0")
                        .frame(width: self.getItemWidth(containerWidth: geometry.size.width) * 2 + self.spacing, height: self.getItemHeight(containerHeight: geometry.size.height))
                        .background(Color.yellow)
                }

                Button(action: {}) {
                    Text(".")
                        .frame(width: self.getItemWidth(containerWidth: geometry.size.width), height: self.getItemHeight(containerHeight: geometry.size.height))
                        .background(Color.yellow)
                }
            }

            }.frame(maxWidth: .infinity, maxHeight: .infinity)
        }
    }
}

#if DEBUG
struct ContentView_Previews : PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

看起来像这样: