In my application, I have NavigationStack presented as a sheet, and I intend to dynamically adjust its height while pushing views within it. I'm utilizing a global observable variable to manage the height and everything works fine except that the height changes abruptly without any animation. It abruptly transitions from one height to another.
The issue can be reproduced using the following code:
#Preview {
@Previewable @State var height: CGFloat = 200
Text("Parent View")
.sheet(isPresented: .constant(true)) {
NavigationStack {
Form {
NavigationLink("Button") {
RoundedRectangle(cornerRadius: 20)
.fill(Color.blue)
.frame(height: 200)
.navigationTitle("Child")
.onAppear {
withAnimation {
height = 300
}
}
}
}
.navigationTitle("Parent")
.navigationBarTitleDisplayMode(.inline)
.presentationDetents([.height(height)])
.onAppear {
withAnimation {
height = 150
}
}
}
}
}
My issue has been solved on Stack Overflow by Benzy Neez.
struct ContentView: View {
let detents: Set<PresentationDetent> = [.height(150), .height(300)]
@State private var selectedDetent: PresentationDetent = .height(150)
@State private var actualHeight: CGFloat?
var body: some View {
Text("Parent View")
.sheet(isPresented: .constant(true)) {
NavigationStack {
Form {
NavigationLink("Button") {
GeometryReader { proxy in
RoundedRectangle(cornerRadius: 20)
.fill(.blue)
.navigationTitle("Child")
.frame(maxHeight: actualHeight)
.animation(.default, value: actualHeight)
.onChange(of: proxy.size.height) { _, newVal in
actualHeight = newVal
}
}
.onAppear {
selectedDetent = .height(300)
}
}
}
.navigationTitle("Parent")
.navigationBarTitleDisplayMode(.inline)
.presentationDetents(detents, selection: $selectedDetent)
.onAppear {
selectedDetent = .height(150)
}
}
}
}
}