< How to create different layouts using size classes | How to add horizontal and vertical scrolling using ScrollView > |
Updated for Xcode 12.5
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")
}
}
}
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.
SPONSORED ViRE offers discoverable way of working with regex. It provides really readable regex experience, code complete & cheat sheet, unit tests, powerful replace system, step-by-step search & replace, regex visual scheme, regex history & playground. ViRE is available on Mac & iPad.
Sponsor Hacking with Swift and reach the world's largest Swift community!
Link copied to your pasteboard.