History
Loading...
Loading...
September 6, 2025
Layout protocol to create custom layouts that automatically adapt to content changes. Instead of hardcoding spacing values, leverage ProposedViewSize and LayoutSubviews to build truly responsive designs that work across all screen sizes.Custom Layout implementations provide precise control over child view positioning while automatically participating in SwiftUI's layout system. This approach creates reusable components that handle dynamic content sizing, device rotation, and accessibility scaling without manual intervention.
struct FlexibleGrid: Layout {
let spacing: CGFloat
let minItemWidth: CGFloat
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
let width = proposal.width ?? 0
let columns = max(1, Int(width / minItemWidth))
let itemWidth = (width - CGFloat(columns - 1) * spacing) / CGFloat(columns)
let rows = ceil(Double(subviews.count) / Double(columns))
let totalHeight = CGFloat(rows) * itemWidth + CGFloat(rows - 1) * spacing
return CGSize(width: width, height: totalHeight)
}
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
let columns = max(1, Int(bounds.width / minItemWidth))
let itemWidth = (bounds.width - CGFloat(columns - 1) * spacing) / CGFloat(columns)
for (index, subview) in subviews.enumerated() {
let column = index % columns
let row = index / columns
let x = bounds.minX + CGFloat(column) * (itemWidth + spacing)
let y = bounds.minY + CGFloat(row) * (itemWidth + spacing)
subview.place(at: CGPoint(x: x, y: y),
proposal: ProposedViewSize(width: itemWidth, height: itemWidth))
}
}
}The Layout protocol integrates seamlessly with SwiftUI's declarative paradigm, offering better performance than GeometryReader-based solutions while maintaining automatic invalidation when content changes. This results in more maintainable code and consistent behavior across different devices and orientations.