Reputation: 83
Let's say I have a circle that I want to change the radius of upon interaction. I want the radius to be defined as a percentage of a view height. I have the following:
struct ButtonView: View {
@State private var radius: CGFloat = 0.1 * geometry.size.height
var body: some View {
GeometryReader { geometry in
Button(action: {
withAnimation(.easeIn) { () -> Result in
self.radius = 0.1 * geometry.size.height
}
}) {
Circle().frame(width: self.radius, height: self.radius)
}
.onLongPressGesture(minimumDuration: 0, maximumDistance: 0, pressing: { (true) in
self.radius = 0.1 * geometry.size.height - 10
}) {}
}
}
}
My problem is that I cannot reference 'geometry.size.height' in the variable statement because it is not nested in the GeometryReader. I've tried using 'UIScreen.main.bounds.width,' but this gives the height of the entire screen. In my circumstance, I'm interested in attaining the height of the view above a tab bar, as ButtonView is nested within one.
Upvotes: 2
Views: 102
Reputation: 299325
A State variable's initial value can't be based on a specific layout. When the struct is created, it doesn't know what the layout is. But you're free to use the GeometryReader's proxy during layout. For example, this scales the circle between 10% and 50% of the view's height. Note the use of maxHeight
here in the frame.
struct ButtonView: View {
@State private var scale: CGFloat = 0.1
var body: some View {
GeometryReader { proxy in
Button(action: { self.scale = (self.scale == 0.1) ? 0.5 : 0.1 }) {
Circle()
}
.frame(maxHeight: proxy.size.height * self.scale)
}
}
}
If you want to capture the information into a State variable on the first appearance, then you can do that in an onAppear
block.
struct ButtonView: View {
@State private var radius: CGFloat = 0.0
var body: some View {
GeometryReader { proxy in
Button(action: { self.radius = 0.5 * proxy.size.height }) {
Circle()
}
.frame(maxHeight: self.radius)
.onAppear { self.radius = 0.1 * proxy.size.height}
}
}
Upvotes: 2