What's wrong with the following code that the viewSize
height remains zero despite having a frame
modifier set to height 60?
struct TestGeometryModifierView: View {
@State var viewSize:CGSize = .zero
var body: some View {
Color.red
.onGeometryChange(for: CGSize.self) { proxy in
proxy.size
} action: { newValue in
viewSize = newValue
print("View Size \(newValue)")
}
.frame(height:viewSize.height)
}
}
#Preview {
TestGeometryModifierView()
.frame(height:60)
}
The print statement on console shows only one line. I expect it to change when frame height is set on the view.
View Size (402.0, 0.0)
A Color
is greedy and consumes as much space as possible. However, you are also setting the height using .frame
and this height is initialized to zero. So on initial show, the width is as wide as possible, but the height is zero.
The height you are measuring using .onGeometryChange
is therefore zero, in other words, the value that the state variable was initialized with. Since the size does not change, .onGeometryChange
is not triggered again.
The height of 60 that you are setting on the surrounding view has no impact on the view that you are measuring with .onGeometryChange
. So this additional .frame
modifier does not cause .onGeometryChange
to trigger.
If you are trying to measure the full size available then you could use an optional for the state variable instead:
@State var viewSize: CGSize?
Color.red
.onGeometryChange(for: CGSize.self) { proxy in
// ... as before
}
.frame(height: viewSize?.height)
The modifier .onGeometryChange
is still only triggered once because the initial size is the same as the size that is set by the .frame
modifier. But now, the state variable measures a useful value:
View Size (393.0, 60.0)