I’ve got a simple HStack
with subviews inside. How can I tell the first subview to be 60% the size of the HStack
without using a GeometryReader
?
struct ContentView: View {
var body: some View {
HStack {
Color.red.opacity(0.3)
Color.brown.opacity(0.4)
Color.yellow.opacity(0.6)
}
}
}
The code above makes each subview the same size. But I want the first one to be 60% regardless of it’s content. In this example, it is a color, but it could be anything.
The HStack
is dynamic in size.
Edit: Why no GeometryReader
?
When I want to place multiple of those HStacks inside a ScrollView
, they overlap, because the GeometryReader’s height is only 10 Point. As mentioned above, the Color
views could be anything, so I used VStacks
with cells in it that have dynamic heights.
struct ContentView: View {
var body: some View {
ScrollView(.vertical) {
ProblematicView()
ProblematicView()
}
}
}
struct ProblematicView: View {
var body: some View {
GeometryReader { geo in
HStack(alignment: .top) {
VStack {
Rectangle().frame(height: 20)
Rectangle().frame(height: 30)
Rectangle().frame(height: 20)
Rectangle().frame(height: 40)
Rectangle().frame(height: 20)
}
.foregroundColor(.red.opacity(0.3))
.frame(width: geo.size.width * 0.6)
.overlay(Text("60%").font(.largeTitle))
VStack {
Rectangle().frame(height: 10)
Rectangle().frame(height: 30)
Rectangle().frame(height: 20)
}
.foregroundColor(.brown.opacity(0.4))
.overlay(Text("20%").font(.largeTitle))
VStack {
Rectangle().frame(height: 5)
Rectangle().frame(height: 10)
Rectangle().frame(height: 24)
Rectangle().frame(height: 10)
Rectangle().frame(height: 17)
Rectangle().frame(height: 13)
Rectangle().frame(height: 10)
}
.foregroundColor(.yellow.opacity(0.6))
.overlay(Text("20%").font(.largeTitle))
}
}
.border(.blue, width: 3.0)
}
}
As you can see, the GeometryReader
‘s frame is too small in height. It should be as high as the HStack
. That causes the views to overlap.
2
Answers
You can set by
.frame
&UIScreen.main.bounds.size.width * (your width ratio)
calculation.Example
Using GeometryReader
I don’t know the exact reason (might be a bug in
GeometryReader
), but placing theGeometryReader
outside theScrollView
, and passing down its width makes your code behave as you expect.Result: