Layout in SwiftUI — Nicola De Filippo

Nicola De Filippo
4 min readApr 13, 2021

Vertical Stack

In the previous post we saw a single object in the view, but to build a nice and helpful interface we need to combine more objects. We start with a simple example, we want a text and a button.

VStack() {
Button(action: {

}) {
Text("Press")
.padding()
.foregroundColor(.white)
.background(LinearGradient(gradient: Gradient(colors: [Color.black, Color.green]), startPoint: .trailing, endPoint: .leading
))
.clipShape(Ellipse())
}
Text("Me")
.foregroundColor(Color.red)
}

In the code, I used a vertical stack (VStack) the object is showed as in the column. See the picture:

It’s possible to also align the element in the stack, to leading (left), to right (trailing) or center (the default). To add the spacing between the elements it used the spacing property.

VStack(alignment: .leading, spacing: 20) {
Button(action: {

}) {
Text("Press")
.padding()
.foregroundColor(.white)
.background(LinearGradient(gradient: Gradient(colors: [Color.black, Color.green]), startPoint: .trailing, endPoint: .leading
))
.clipShape(Ellipse())
}
Text("Me")
.foregroundColor(Color.red)
}

To have:

How we can push the button and the text on the top of the view? We have to use the Spacer object:

struct ContentView: View {
var body: some View {
VStack(alignment: .center, spacing: 20) {
Button(action: {

}) {
Text("Press")
.padding()
.foregroundColor(.white)
.background(LinearGradient(gradient: Gradient(colors: [Color.black, Color.green]), startPoint: .trailing, endPoint: .leading
))
.clipShape(Ellipse())
}
Text("Me")
.foregroundColor(Color.red)
Spacer()
}
}
}

We added the Spacer object after the Text, so we fill the space and the other objects are pushed up.

If we push the Spacer before the button, the objects are pushed down.

Horizontal Stack

Dual of the Vertical Stack is the horizontal stack (HStack):

struct ContentView: View {
var body: some View {
HStack(alignment: .center, spacing: 20) {
Button(action: {

}) {
Text("Press")
.padding()
.foregroundColor(.white)
.background(LinearGradient(gradient: Gradient(colors: [Color.black, Color.green]), startPoint: .trailing, endPoint: .leading
))
.clipShape(Ellipse())
}
Text("Me")
.foregroundColor(Color.red)

}
}
}

To have:

The alignment, in this case, is center, top and bottom. See top as an example:

struct ContentView: View {
var body: some View {
HStack(alignment: .top, spacing: 20) {
Button(action: {

}) {
Text("Press")
.padding()
.foregroundColor(.white)
.background(LinearGradient(gradient: Gradient(colors: [Color.black, Color.green]), startPoint: .trailing, endPoint: .leading
))
.clipShape(Ellipse())
}
Text("Me")
.foregroundColor(Color.red)

}
}
}

It looks as:

With the HStack we using the Spacer to push the objects on the left or the right. For example, if we write the Spacer after the Text:

struct ContentView: View {
var body: some View {
HStack(alignment: .center, spacing: 20) {
Button(action: {

}) {
Text("Press")
.padding()
.foregroundColor(.white)
.background(LinearGradient(gradient: Gradient(colors: [Color.black, Color.green]), startPoint: .trailing, endPoint: .leading
))
.clipShape(Ellipse())
}
Text("Me")
.foregroundColor(Color.red)
Spacer()

}
}
}

To have:

ZStack

SwiftUI has also a ZStack, it’s as a pile. See the code:

struct ContentView: View {
var body: some View {
ZStack() {
Text("I'm level 0")
.foregroundColor(Color.white)
.padding(100)
.background(Color.gray)
Text("I'm level 1")
.foregroundColor(Color.blue)
}
}
}

If we run this code we see that the second label (“I’m level 1”), override the first one:

In this way it’s not helpful, to move the second label we can use the offset(x, y) where the X is relative to the beginning of the first element, the same for the Y.

struct ContentView: View {
var body: some View {
ZStack() {
Text("I'm level 0")
.foregroundColor(Color.white)
.padding(100)
.background(Color.gray)
Text("I'm level 1")
.foregroundColor(Color.blue)
.offset(x: 0, y: 100)
}
}
}

To have:

It does not seem very cool example, but we’ll see nice things in the next post when I’ll show how to use the image.

Note: English is not my native language, so I’m sorry for some errors. I appreciate it if your correct me.

Originally published at https://nicoladefilippo.com on April 13, 2021.

--

--