50 lines
1.6 KiB
Swift
50 lines
1.6 KiB
Swift
import SwiftUI
|
|
|
|
struct FlexibleColumnView<Content, Inner>: 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)
|
|
}
|
|
}
|