I can't figure out how to align the content of this view:
I tried many different approaches:
Nothing seems to work :(
import SwiftUI
struct Welcome: View {
var body: some View {
VStack {
Text("Welcome to XXX")
.font(.title).bold()
HStack {
Image(systemName: "magnifyingglass")
.foregroundColor(Color(.systemOrange))
.imageScale(.large)
.padding()
VStack(alignment: .leading) {
Text("Lorem ipsum dolor")
.font(.headline)
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore")
.font(.subheadline)
.foregroundColor(Color(.lightText))
}
}.padding()
HStack {
Image(systemName: "command")
.foregroundColor(Color(.systemOrange))
.imageScale(.large)
.padding()
VStack(alignment: .leading) {
Text("Lorem ipsum dolor")
.font(.headline)
Text("Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.")
.font(.subheadline)
.foregroundColor(Color(.lightText))
}
}.padding()
HStack {
Image(systemName: "cube")
.foregroundColor(Color(.systemOrange))
.imageScale(.large)
.padding()
VStack(alignment: .leading) {
Text("At vero eos et accusamus")
.font(.headline)
Text("At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque ")
.font(.subheadline)
.foregroundColor(Color(.lightText))
}
}.padding()
Button(action: {
print("skip")
}) {
HStack {
Spacer()
Text("Skip")
.font(.subheadline)
Spacer()
}
.foregroundColor(Color(.systemOrange))
}.padding(.top, 60)
Button(action: {
print("continue")
}) {
HStack {
Spacer()
Text("Sign In")
.font(.subheadline)
Spacer()
}
.padding(12)
.foregroundColor(Color(.label))
.background(Color(.systemOrange))
.cornerRadius(12)
}.padding()
}
}
}
It's quite annoying that the Human Interface Guidelines recommend creating welcome screens such as this and they don't provide a simple to do it.
HStack positions views in a horizontal line, VStack positions them in a vertical line, and ZStack overlays views on top of one another.
You can use 3 kinds of stacks with SwiftUI: VStack, a vertical stack, which shows views in a top-to-bottom list. HStack, a horizontal stack, which shows views in a left-to-right list. ZStack, a depth-based stack, which shows views in a back-to-front list.
You just need to add Spacer() & embed your view in VStack & HStack to force push the view to the top. Show activity on this post. You can remove the HStack and place the Spacer() within your VStack which will force the view to the top.
To align a text view along the horizontal axis, you need to use . frame() modifier with maxWidth set to . infinity and alignment to the alignment you want.
Just to get a little deeper on this issue (please, consider that the @Mycroft's answer is correct): In order to get the UI shown in the question the Spacer
is necessary, it's not optional. I created a minimum viable example to show exactly what would happen without the Spacer
view:
struct ContentView: View {
var body: some View {
VStack {
HStack {
Image(systemName: "magnifyingglass")
.foregroundColor(Color(.systemOrange))
VStack(alignment: .leading) {
Text("Sed ut perspiciatis unde omnis iste natus")
}
}
HStack {
Image(systemName: "magnifyingglass")
.foregroundColor(Color(.systemOrange))
VStack(alignment: .leading) {
Text("Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.")
}
}
HStack {
Image(systemName: "magnifyingglass")
.foregroundColor(Color(.systemOrange))
VStack(alignment: .leading) {
Text("At vero eos ")
}
}
}
}
}
The result is:
As you can see the result is completely misaligned. So, you must add the Spacer
view in order to get the alignment you want.
struct ContentView: View {
var body: some View {
VStack {
HStack {
Image(systemName: "magnifyingglass")
.foregroundColor(Color(.systemOrange))
VStack(alignment: .leading) {
Text("Sed ut perspiciatis unde omnis iste natus")
}
Spacer()
}
HStack {
Image(systemName: "magnifyingglass")
.foregroundColor(Color(.systemOrange))
VStack(alignment: .leading) {
Text("Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.")
}
Spacer()
}
HStack {
Image(systemName: "magnifyingglass")
.foregroundColor(Color(.systemOrange))
VStack(alignment: .leading) {
Text("At vero eos ")
}
Spacer()
}
}
}
}
In the layout above you have "two columns", the left one with the images and the right one with the texts. If you don't specify any size, the layout system will position the images and then it will give the remaining space to the texts. But there's another option if you need to specify specific sizes: if you need the image left column to be, for example, half of the screen you can use GeometryReader
:
struct ContentView: View {
var body: some View {
GeometryReader { g in
VStack {
HStack {
HStack {
Spacer()
Image(systemName: "magnifyingglass")
.foregroundColor(Color(.systemOrange))
}
.frame(width: g.size.width/2.0)
VStack(alignment: .leading) {
Text("Sed ut perspiciatis unde omnis iste natus")
}
Spacer()
}
HStack {
HStack {
Spacer()
Image(systemName: "magnifyingglass")
.foregroundColor(Color(.systemOrange))
}
.frame(width: g.size.width/2.0)
VStack(alignment: .leading) {
Text("Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Sed ut ")
}
Spacer()
}
HStack {
HStack {
Spacer()
Image(systemName: "magnifyingglass")
.foregroundColor(Color(.systemOrange))
}
.frame(width: g.size.width/2.0)
VStack(alignment: .leading) {
Text("At vero eos ")
}
Spacer()
}
}
}
}
}
Adding a spacer seems to do the trick :
HStack {
Image(systemName: "cube")
.foregroundColor(Color(.systemOrange))
.imageScale(.large)
.padding()
VStack(alignment: .leading) {
Text("At vero eos et accusamus")
.font(.headline)
Text("At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque ")
.font(.subheadline)
.foregroundColor(Color(.lightText))
}
Spacer()
}.padding()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With