Every View
needs to return one type of view. Which is why this is OK.
var body: some View {
Text("Hello World")
}
But this isn't as it returns x2 views.
var body: some View {
Text("Hello World")
Text("This is another text view")
}
The way we get around this is with stacks.
var body: some View {
VStack {
Text("Hello World")
Text("This is inside a stack")
}
}
VStack(alignment: .leading) {
Text("Hello World")
Text("This is inside a stack")
}
VStack(spacing: 20) {
Text("Welcome to Family Pool").font(.title)
Text("Create your pool by swiping through the next couple of screens.")
}
HStack(spacing: 20) {
Text("Hello World")
Text("This is inside a stack")
}
ZStack
arranges things by depth. It makes the views overlap.
ZStack {
Text("Hello World")
Text("This is inside a stack")
}
From Stanford:
- If even one of its children is fully flexible size, then the
ZStack
will be too.
An alternative is .backgroundModifier
.
Text("hello").background(Rectangle().foregroundColor(.red))
This is similar to making a ZStack
of Text
and Rectangle
, however there is a big difference. In this case the resultant view is sized to the text (the Rectangle
is not involved). In otherwords the Text
solely determines the layout of this mini-ZStack of two things.
But it is a handy trick for when you want the background of the text to be a certain color, but not be flexible to fill the entire view.
Same layout rules as .background
, but stacked the other way around.
Circle().overlay(Text("Hello").foregroundColor(.red), alignment: .center)
This will be sized to the Circle (i.e. it will be fully-flexible size). The Text
will be stacked on top of the Circle
with the specified alignment inside the Circle
.
Vertical and horizontal stacks automatically fill their available space in the center. If you want to push the content to the side, you need to use a spacer.
These automatically take up all the remaining space. So if you add one at the end of a VStack
it wil push all your views to the top of the screen.
A container view that arranges its child views in a grid that grows horizontally, creating items only as needed.
import SwiftUI
struct ContentView: View {
var rows: [GridItem] = Array(repeating: .init(.fixed(20)), count: 2)
var body: some View {
ScrollView(.horizontal) {
LazyHGrid(rows: rows, alignment: .top) {
ForEach((0...79), id: \.self) {
let codepoint = $0 + 0x1f600
let codepointString = String(format: "%02X", codepoint)
Text("\(codepointString)")
.font(.footnote)
let emoji = String(Character(UnicodeScalar(codepoint)!))
Text("\(emoji)")
.font(.largeTitle)
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
A view that arranges its children in a line that grows horizontally, creating items only as needed.
- These lazy versions don't build any of their Views that are not visible.
- They also size themselves to fit their views.
- So they don't take up all the space offerred to them even if they have flexible views inside.
- You'd use these when you have a stack that is in a
ScrollView
.
import SwiftUI
struct ContentView: View {
var body: some View {
ScrollView(.horizontal) {
LazyHStack(alignment: .top, spacing: 10) {
ForEach((0...79), id: \.self) {
let codepoint = $0 + 0x1f600
let codepointString = String(format: "%02X", codepoint)
Text("\(codepointString)")
.font(.footnote)
let emoji = String(Character(UnicodeScalar(codepoint)!))
Text("\(emoji)")
.font(.largeTitle)
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}