Greetings, traveler!
When SwiftUI introduced the Layout protocol in iOS 16, it also brought a powerful companion — AnyLayout. This type-erased wrapper allows developers to switch between different layout types without losing state or interrupting animations. It solves a common limitation in earlier SwiftUI versions, where changing from one layout (such as HStack) to another (VStack) caused the view hierarchy to rebuild completely.
Before iOS 16
Before AnyLayout, layout switching often looked like this:
if collapsed {
ZStack {
Image(systemName: "globe")
Image(systemName: "magnifyingglass")
Image(systemName: collapsed ? "sparkles" : "waveform")
}
} else {
VStack {
Image(systemName: "globe")
Image(systemName: "magnifyingglass")
Image(systemName: collapsed ? "sparkles" : "waveform")
}
}
Although functional, this approach caused SwiftUI to treat the layout change as a removal and insertion of new views. As a result, any smooth transition between layouts was lost — the system destroyed the previous hierarchy and created a new one. For developers seeking fluid animations or persistent view states, this was a significant limitation.
What Is AnyLayout
AnyLayout is a type-erased container for any type conforming to the Layout protocol. It provides a way to switch between layouts dynamically while keeping SwiftUI aware that the underlying view hierarchy remains the same.
Instead of declaring separate conditional views, you define a single layout variable that can change its layout type:
layout {
Image(systemName: "globe")
Image(systemName: "magnifyingglass")
Image(systemName: collapsed ? "sparkles" : "waveform")
}With AnyLayout, SwiftUI preserves the identity of child views and smoothly animates layout transitions between different arrangements.
Example: Animated Layout Toggle
Here’s an example that combines ZStackLayout and HStackLayout in a single view using AnyLayout. The layout changes when the user taps the screen.
struct ContentView: View {
@State private var collapsed = true
private var layout: AnyLayout {
collapsed ? AnyLayout(ZStackLayout()) : AnyLayout(HStackLayout())
}
var body: some View {
layout {
Group {
Image(systemName: "globe")
Image(systemName: "magnifyingglass")
Image(systemName: collapsed ? "sparkles" : "waveform")
}
.font(.system(size: 50))
.padding()
.background(in: .circle)
.backgroundStyle(Color.primary)
.foregroundColor(Color(.systemBackground))
.clipShape(.circle)
.animation(.bouncy, value: collapsed)
}
.onTapGesture {
collapsed.toggle()
}
}
}When tapped, the icons smoothly rearrange from overlapping circles (ZStackLayout) to a horizontal line (HStackLayout) and back again. Because the same view hierarchy is maintained, SwiftUI animates the transition naturally without abrupt changes.
Conclusion
AnyLayout provides a simple yet powerful way to achieve smooth layout transitions in SwiftUI. By abstracting away specific layout types, it lets you dynamically change your layout without losing view identity or animation continuity. If your design requires adaptive, animated structures, AnyLayout is one of the most elegant tools introduced with the new SwiftUI layout system in iOS 16.
