< How to create different layouts using size classes | How to add horizontal and vertical scrolling using ScrollView > |
Updated for Xcode 14.2
SwiftUI lets us monitor the current size class to decide how things should be laid out, for example switching from a HStack
when space is plentiful to a VStack
when space is restricted.
With a little thinking, we can write a new AdaptiveStack
view that automatically switches between horizontal and vertical layouts for us. This makes creating great layouts on iPad simpler, because our layouts will automatically adjust to split view and slipover scenarios.
Here’s how it looks:
struct AdaptiveStack<Content: View>: View {
@Environment(\.horizontalSizeClass) var sizeClass
let horizontalAlignment: HorizontalAlignment
let verticalAlignment: VerticalAlignment
let spacing: CGFloat?
let content: () -> Content
init(horizontalAlignment: HorizontalAlignment = .center, verticalAlignment: VerticalAlignment = .center, spacing: CGFloat? = nil, @ViewBuilder content: @escaping () -> Content) {
self.horizontalAlignment = horizontalAlignment
self.verticalAlignment = verticalAlignment
self.spacing = spacing
self.content = content
}
var body: some View {
Group {
if sizeClass == .compact {
VStack(alignment: horizontalAlignment, spacing: spacing, content: content)
} else {
HStack(alignment: verticalAlignment, spacing: spacing, content: content)
}
}
}
}
struct ContentView: View {
var body: some View {
AdaptiveStack {
Text("Horizontal when there's lots of space")
Text("but")
Text("Vertical when space is restricted")
}
}
}
Download this as an Xcode project
To try it out, run the app in an iPad simulator, then try different sizes of split view – you’ll see ContentView
automatically switch to a VStack
when space runs low.
Now to explain how the custom view works:
horizontalSizeClass
environment key, so that it will be updated every time that size class changes.CGFloat
for spacing, because that’s what VStack
and HStack
work with. If you wanted even more control you could add horizontalSpacing
and verticalSpacing
properties.content
property is a function that accepts no parameters and returns some sort of content, which is the view builder end users will rely on to create their layouts.body
property we can read the horizontal size class, then wrap a call to content()
in either a VStack
or HStack
.And that’s it! The actual code isn’t as hard you might imagine, but it gives us some really helpful flexibility.
SAVE 50% To celebrate WWDC23, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.
Link copied to your pasteboard.