strikerdude10
strikerdude10

Reputation: 683

Make 2x2 grid based on screen width

Sorry if this is a simple question but I'm just starting out with SwiftUI and I'm trying to figure out how to make a 2x2 grid of views based on the width of the screen. Meaning that each square has a width and height of have the screen width and they are arranged in a 2x2 grid with no padding.

I've been trying with two HStacks with two views in each placed on top of each other but the view size inside the HStack seems to dictate the HStack's height.

Code for Views I'm trying to arrange into the 2x2 grid:

var body: some View {
        VStack {
            TextField("0", text: $value)
                .multilineTextAlignment(.center)
                .textFieldStyle(PlainTextFieldStyle())
                .font(.system(size: 40, weight: .semibold, design: .rounded))
                .border(Color.black)
                .padding()

            Text(title)
                .padding([.leading, .bottom, .trailing])
                .font(.system(size: 14, weight: .regular, design: .rounded))
            }
                .background(Color.green)
                .cornerRadius(10)
                .overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.black, lineWidth: 5))
    }

Upvotes: 0

Views: 1951

Answers (2)

meaning-matters
meaning-matters

Reputation: 22946

This can be done using a GeometryReader:

struct ContentView: View
{
    var body: some View
    {
        GeometryReader
        { geometry in
            self.useProxy(geometry)
        }
    }

    func useProxy(_ geometry: GeometryProxy) -> some View
    {
        let dimension = min(geometry.size.width, geometry.size.height)
        return VStack
        {
            HStack(spacing: 0)
            {
                Text("Top Left")
                    .frame(width: dimension / 2, height: dimension / 2)
                    .border(Color.black)

               Text("Top Right")
                   .frame(width: dimension / 2, height: dimension / 2)
                   .border(Color.black)
            }

            HStack(spacing: 0)
            {
                Text("Bottom Left")
                    .frame(width: dimension / 2, height: dimension / 2)
                    .border(Color.black)

               Text("Bottom Right")
                   .frame(width: dimension / 2, height: dimension / 2)
                   .border(Color.black)
            }
        }
    }
}

Watch (the first part of) this WWDC video to hear about the layout system of SwiftUI.

Upvotes: 1

LuLuGaGa
LuLuGaGa

Reputation: 14388

I find that using A combination of HStacks, VStacks and aspectRatio(_ aspectRatio: CGFloat? = nil, contentMode: ContentMode) works best for forcing certain proportions on views:

struct ContentView: View {

    var body: some View {
        VStack(spacing: 0) {
            HStack(spacing: 0) {
                Rectangle().fill(Color.red)
                    .aspectRatio(1.0, contentMode: .fit)
                Rectangle().fill(Color.green)
                    .aspectRatio(1.0, contentMode: .fill)
            }
            HStack(spacing: 0) {
                Rectangle().fill(Color.blue)
                    .aspectRatio(1.0, contentMode: .fit)
                Rectangle().fill(Color.yellow)
                    .aspectRatio(1.0, contentMode: .fill)
            }
        }.aspectRatio(contentMode: .fit)
    }
}

Results in a layout like this:

2x2 grid

Upvotes: 2

Related Questions