I tried to build a grid view that loads lazily on both vertical and horizontal axes, the main goal is building a calendar for a list of employees. Both the list and the calendar interval can be very large so they have to be rendered lazily. I've tried LazyHGrid
and LazyVGrid
but they only render views lazily on one direction. The further approach uses one LazyVStack
for the whole view and one LazyHStack
for each row, the loading is lazy (check print in the console) but while scrolling the views, it loses their position and the grid gets broken. I also need fixed headers, that is achieved in the code using pinnedViews
.
struct ContentView: View {
var body: some View {
ScrollView([.horizontal, .vertical]) {
LazyVStack(spacing: 20, pinnedViews: .sectionHeaders) {
Section(header: columnHeaders) {
ForEach(0..<20) { row in
LazyHStack(spacing: 20, pinnedViews: .sectionHeaders) {
Section(header: rowHeader(with: "Employee \(row)")) {
ForEach(0..<100) { column in
Text("Cell \(row), \(column)")
.foregroundColor(.white)
.font(.largeTitle)
.frame(width: 200, height: 100)
.background(Color.red)
.onAppear {
print("Cell \(row), \(column)")
}
}
}
}
}
}
}
}
}
var columnHeaders: some View {
LazyHStack(spacing: 20, pinnedViews: .sectionHeaders) {
Section(header: rowHeader(with: "")) {
ForEach(0..<100) { column in
Text("Header \(column)")
.frame(width: 200, height: 100)
.background(Color.white)
}
}
}
}
func rowHeader(with label: String) -> some View {
Text(label)
.frame(width: 100, height: 100)
.background(Color.white)
}
}
Tried what was said above.