Reputation: 929
I have a dynamic SwiftUI view where I pass information through parameter. After, I try to make copies of the view using ForEach loop. The views appear as usual vertically in a Stack. However, I would like to present the all views in three different lines. Could anyone please present a efficient solution?
I want this design:
But I have got this:
My code:
struct AllDaysView: View {
@Binding var hasMenuShown: Bool
var days: [String] = NextDaysView().days
var body: some View {
VStack {
MenuBarView(hasMenuShown: $hasMenuShown)
ForecastButtonsView()
HStack {
ForEach(days, id: \.self) { day in
SingleDaySummaryView(day: day)
}
}
Spacer()
}
}
}
Upvotes: 2
Views: 3715
Reputation: 3446
First, let's make a way to divide the array in groups of three.
extension Array {
func dividedIntoGroups(of i: Int = 3) -> [[Element]] {
var copy = self
var res = [[Element]]()
while copy.count > i {
res.append( (0 ..< i).map { _ in copy.remove(at: 0) } )
}
res.append(copy)
return res
}
}
Change the days
var:
var days: [String] = NextDaysView().days.dividedIntoGroups(of: 3)
Now, let's make the new code for body
:
VStack {
MenuBarView(hasMenuShown: $hasMenuShown)
ForecastButtonsView()
ForEach(days, id: \.self) { dayRow in
HStack {
ForEach(dayRow, id: \.self) { day in
SingleDaySummaryView(day: day)
}
}
}
Spacer()
}
In this code, you can easily change the number of views per row, but it seems quite difficult to make it really dynamic. When you want to do that, you could use GeometryReader
to get the screen width, but to calculate the number of views per row, you will of course also need the width of one view, and that's tricky. This article may contain information that could lead to a solution: https://swiftui-lab.com/communicating-with-the-view-tree-part-1/
I couldn't really test this code, because I'm not working on my Mac right now, but hopefully it works or will at least help you!
Upvotes: 2