Skip to content

Instantly share code, notes, and snippets.

@vahotm
Last active June 7, 2023 08:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vahotm/69b750bf1572dc499122095c30f042f7 to your computer and use it in GitHub Desktop.
Save vahotm/69b750bf1572dc499122095c30f042f7 to your computer and use it in GitHub Desktop.
A non-lazy alternative to LazyVGrid. The difference from LazyVGrid is that VGrid gives equal height to its cells based on the highest cell, hence its non-laziness.
import Foundation
import SwiftUI
struct VGrid<Cell: View>: View {
struct CollectionRow<Cell: View>: View {
let indices: Range<Int>
let numberOfColumns: Int
let spacing: CGFloat
let minHeight: CGFloat
@ViewBuilder var cellBuilder: (Int) -> Cell
@ViewBuilder
var body: some View {
HStack(spacing: spacing) {
ForEach(indices, id: \.self) { index in
cellBuilder(index)
.frame(minHeight: minHeight)
}
ForEach(0..<(numberOfColumns - indices.count), id: \.self) { _ in
Spacer()
.frame(maxWidth: .infinity)
}
}
}
}
let configuration: VGridConfiguration
@ViewBuilder var cellBuilder: (Int) -> Cell
@State private var maxRowHeight: CGFloat = 0.0
@ViewBuilder
var body: some View {
VStack(alignment: configuration.alignment, spacing: configuration.vSpacing) {
ForEach(ranges, id: \.self) { rowRange in
CollectionRow(
indices: rowRange,
numberOfColumns: configuration.numberOfColumns,
spacing: configuration.hSpacing,
minHeight: maxRowHeight,
cellBuilder: cellBuilder)
.fixedSize(horizontal: false, vertical: true)
.readSize { size in
maxRowHeight = max(size.height, maxRowHeight)
}
.frame(minHeight: maxRowHeight)
}
}
}
private var ranges: [Range<Int>] {
stride(from: 0, to: configuration.itemsCount, by: configuration.numberOfColumns).map { i in
let upperBound = min(i + configuration.numberOfColumns, configuration.itemsCount)
return i..<upperBound
}
}
init(_ configuration: VGridConfiguration, cellBuilder: @escaping (Int) -> Cell) {
self.configuration = configuration
self.cellBuilder = cellBuilder
}
}
struct VGridConfiguration {
let numberOfColumns: Int
let itemsCount: Int
let alignment: HorizontalAlignment
let hSpacing: CGFloat
let vSpacing: CGFloat
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment