I am trying to create a new grid structure in SwiftUI to show cards with variable heights. To that extent, I use several LazyVStack
s in a HStack
and have a condition to display my data items in the correct order. This view works alone, adapts the number of columns to the size of the screen, but when using it in a ScrollView
, its size is not computed properly and the following views end up beneath the grid instead of below it. Here is the code I used for the grid :
struct StaggeredGrid<Element, Content>: View where Content: View {
var preferredItemWidth: CGFloat
var data: [Element] = []
var content: (Element) -> Content
init(preferredItemWidth: CGFloat, data: [Element], @ViewBuilder content: @escaping (Element) -> Content) {
self.preferredItemWidth = preferredItemWidth
self.data = data
self.content = content
}
var body: some View {
GeometryReader { geometry in
HStack(alignment: .top, spacing: 20) {
ForEach(1...Int(geometry.size.width / preferredItemWidth), id: \.self) { number in
LazyVStack(spacing: 20) {
ForEach(0..<data.count, id: \.self) { index in
if (index+1) % Int(geometry.size.width / preferredItemWidth) == number % Int(geometry.size.width / preferredItemWidth) {
content(data[index])
}
}
}
}
}
.padding([.horizontal])
}
}
}
And the preview to show the behavior :
struct StaggeredGrid_Previews: PreviewProvider {
static var previews: some View {
ScrollView {
VStack {
StaggeredGrid(preferredItemWidth: 160, data: (1...10).map{"Item \($0)"}) { item in
Text(item)
.foregroundColor(.blue)
}
Text("I should be below the grid")
}
}
}
}
Here is a picture of the preview: Wrong appearance in a ScrollView
And a picture when the ScrollView
is commented out:
Expected behavior, ScrollView removed
Thank you in advance for any help or clue about this behavior I do not understand.