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)
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)
Share
Improve this question
edited Mar 28 at 17:54
HangarRash
15.1k5 gold badges20 silver badges55 bronze badges
asked Mar 28 at 11:20
Deepak SharmaDeepak Sharma
6,63110 gold badges66 silver badges161 bronze badges
6
|
Show 1 more comment
1 Answer
Reset to default 2A 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)
frame
isn't actually directly changing the size of the view it modifies? It merely adds an invisible frame around the view. So here you have some red color in a.frame(height:viewSize.height)
, which is in another.frame(height:60)
. The frame on the inside is fixed. It doesn't care about how big the frame on the outside is. – Sweeper Commented Mar 28 at 12:52.frame(height:viewSize.height)
? For views that uses the full height of the size proposal (e.g.Color
), this will always create a 0-height view. For views that ignore the height of the size proposal, the height of the frame will always be the same as the height of the view anyway, so theframe
modifier is redundant. – Sweeper Commented Mar 28 at 13:06GeometryReader
as I readonGeometryChange
can for all intents and purposes replace it. I have a subview in aScrollView
whose height I need to set to height of superview and that is why I was playing around withviewSize
to grab how much space is available. – Deepak Sharma Commented Mar 28 at 13:28