Reputation: 683
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
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
Reputation: 14388
I find that using A combination of HStack
s, VStack
s 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:
Upvotes: 2