I created ListView which represents HStack with 5 elements:
var body: some View {
GeometryReader { geo in
HStack(alignment: .center) {
renderHomeListItem(value: "\(title)", color: .black)
.frame(width: geo.size.width * 0.3)
renderHomeListItem(value: "\(confirmed)", color: Color(UIColor.systemRed))
.frame(width: geo.size.width * 0.15)
renderHomeListItem(value: "\(active)", color: Color(UIColor.systemBlue))
.frame(width: geo.size.width * 0.15)
renderHomeListItem(value: "\(recovered)", color: Color(UIColor.systemGreen))
.frame(width: geo.size.width * 0.15)
renderHomeListItem(value: "\(deaths)", color: Color(UIColor.systemGray))
.frame(width: geo.size.width * 0.15)
}
.fixedSize()
}
}
renderHomeListItem is representing one element in HStack:
@ViewBuilder
private func renderHomeListItem(value: String, color: Color) -> some View {
Text(value)
.padding()
.commonFont(firstListItem == true ? .bold : .regular, style: .caption2)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.foregroundColor(firstListItem == true ? color : .black)
.background(colorScheme == .light ? Color(UIColor.systemGray5) : itemDarkModeBackground)
.cornerRadius(5)
}
And I am calling ListView like this:
@ViewBuilder
private func renderHomeList() -> some View {
LazyVStack {
HomeListItemView(title: homeViewModel.useCaseSelection == .worldwide ? "State" : "Date", confirmed: "C", active: "A", deaths: "D", recovered: "R")
ForEach(homeViewModel.homeScreenDomainItem.listStats) { value in
HomeListItemView(title: value.title,
confirmed: "\(value.confirmed.formatUsingAbbrevation())",
active: "\(value.active.formatUsingAbbrevation())",
deaths: "\(value.deaths.formatUsingAbbrevation())",
recovered: "\(value.recovered.formatUsingAbbrevation())")
}
}
.padding()
}
Problem is that height of elements in ForEach is iterating over each other so I am getting something like this:
I tried to use padding() everywhere, but it is not answer.
CodePudding user response:
That's because of the GeometryReader
.
The simplest solution, if it works in your layout, is to fix the size of the GeometryReader
:
var body: some View {
GeometryReader { geo in
HStack(alignment: .center) {
// renderHomeListItem x 5
}
.fixedSize()
}
// This will avoid the overlaps
.frame(height: someValueHere)
}
Otherwise, if the height cannot be fixed, you need to move the GeometryReader
to wrap the whole LazyVStack
and then pass geo
to HomeListItemView
.
Like this (very schematic):
private func renderHomeList() -> some View {
// Delete the GeometryReader from the HomeListItemView and move it here at the top
GeometryReader { geo in
LazyVStack {
// Create a new parameter in HomeListItemView to pass the geo variable
HomeListItemView(geometry: geo, title: homeViewModel.useCaseSelection == .worldwide ? "State" : "Date", confirmed: "C", active: "A", deaths: "D", recovered: "R")
ForEach(homeViewModel.homeScreenDomainItem.listStats) { value in
// Create a new parameter in HomeListItemView to pass the geo variable
HomeListItemView(geometry: geo, title: value.title,
confirmed: "\(value.confirmed.formatUsingAbbrevation())",
active: "\(value.active.formatUsingAbbrevation())",
deaths: "\(value.deaths.formatUsingAbbrevation())",
recovered: "\(value.recovered.formatUsingAbbrevation())")
}
}
.padding()
}
}