I'm not quite a SwiftUI veteran but I've shipped a couple of apps of moderate complexity. Still, I can't claim that I fully understand it and I'm hoping someone with deeper knowledge could shed some light on this issue:
I have some content that I want to toggle on and off, not unlike .sheet(), but I want more control over it. Here is some "reconstructed" code but it should be able capture the essence:
struct ContentView: View {
@State private var isShown = false
var body: some View {
GeometryReader { g in
VStack {
ZStack(alignment: .top) {
// This element "holds" the size
// while the content is hidden
Color.clear
// Content to be toggled
if self.isShown {
ScrollView {
Rectangle()
.aspectRatio(1, contentMode: .fit)
.frame(width: g.size.width) // This is a "work-around"
} // ScrollView
.transition(.move(edge: .bottom))
.animation(.easeOut)
}
} // ZStack
// Button to show / hide the content
Button(action: {
self.isShown.toggle()
}) {
Text(self.isShown ? "Hide" : "Show")
}
} // VStack
} // GeometryReader
}
}
What it does is, it toggles on and off some content block (represented here by a Rectangle within a ScrollView). When that happens, the content view in transitioned by moving in from the bottom with some animation. The opposite happens when the button is tapped again.
This particular piece of code works as intended but only because of this line:
.frame(width: g.size.width) // This is a "work-around"
Which, in turn, requires an extra GeometryReader, otherwise, the width of the content is animated, producing an unwanted effect (another "fix" I've discovered is using the .fixedSize() modifier but, to produce reasonable effects, it requires content that assumes its own width like Text)
My question to the wise is: is it possible to nicely transition in content encapsulated within a ScrollView without using such "fixes"? Alternatively, is there a more elegant fix for that?
A quick addition to the question following @Asperi's answer: contents should remain animatable. You are my only hope,
–Baglan