import SwiftUI struct FlowLayout: Layout { var spacing: CGFloat = 8 func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize { let width = proposal.width ?? .infinity var x: CGFloat = 0, y: CGFloat = 0, rowHeight: CGFloat = 0 for view in subviews { let size = view.sizeThatFits(.unspecified) if x + size.width > width, x > 0 { x = 0 y += rowHeight + spacing rowHeight = 0 } x += size.width + spacing rowHeight = max(rowHeight, size.height) } return CGSize(width: width.isFinite ? width : x, height: y + rowHeight) } func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) { var x = bounds.minX, y = bounds.minY, rowHeight: CGFloat = 0 for view in subviews { let size = view.sizeThatFits(.unspecified) if x + size.width > bounds.maxX, x > bounds.minX { x = bounds.minX y += rowHeight + spacing rowHeight = 0 } view.place(at: CGPoint(x: x, y: y), proposal: ProposedViewSize(size)) x += size.width + spacing rowHeight = max(rowHeight, size.height) } } }