import SwiftUI struct FlexibleColumnView: View where Content: Identifiable, Inner: View { @Binding var items: [Content] let maximumItemWidth: CGFloat let spacing: CGFloat private let content: (_ item: Content, _ width: CGFloat) -> Inner init(items: Binding<[Content]>, maximumItemWidth: CGFloat = 300, spacing: CGFloat = 20, content: @escaping (_ item: Content, _ width: CGFloat) -> Inner) { self._items = items self.maximumItemWidth = maximumItemWidth self.spacing = spacing self.content = content } var body: some View { GeometryReader { geometry in let totalWidth = geometry.size.width let columnCount = max(Int((totalWidth + spacing) / (maximumItemWidth + spacing)), 1) let totalSpacing = spacing * CGFloat(columnCount + 1) let trueItemWidth = (totalWidth - totalSpacing) / CGFloat(columnCount) let columns = Array(repeating: GridItem(.flexible(), spacing: spacing), count: columnCount) ScrollView { LazyVGrid(columns: columns, spacing: spacing) { ForEach(items) { item in content(item, trueItemWidth) } } .padding(spacing) } } } } #Preview { FlexibleColumnView(items: .constant(MockImage.images), maximumItemWidth: 150) { image, width in image.imageToDisplay .resizable() .aspectRatio(contentMode: .fit) .frame(width: width) } }