Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm trying to create a Calculator using SwiftUI, I'm struggling right now on creating the Grid of buttons to fill the available space horizontally

Right now I'm just trying to make the buttons fill a grid of 3 x 3 of equal height and width

I was able to make them same height by using Spacer() according to this answer but same width is where I'm stuck right now:

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

This is my current output vs an example of the desired output I want. First of all I'm trying to make the buttons to fill current area, later on I will try to make the 0 button to fill 2 cells.

enter image description here enter image description here

like image 972
Frakcool Avatar asked Jun 19 '19 00:06

Frakcool


1 Answers

How about using a GeometryReader(docs here)? They give the dimensions of their parent view to the children. Here's a partial implementation based on what you already have:

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

Looks like this: Live preview

like image 68
piebie Avatar answered Oct 14 '22 08:10

piebie