Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI: How to remove delay from dismissing a sheet?

I want to offset a view when a sheet comes up and set it back when the sheet gets dismissed. The code itself works, but I have a problem.

When the sheet first comes up, everything is running as expected. But when I dismiss the sheet, there is a ~ 1 second delay before the offset goes back to 0. (Running it in the actual simulator shows the same result)

How can I get rid of the delay or control the delay duration?

My code:

import SwiftUI


struct FirstView: View {
    
    @State var showSheet: Bool = false
    
    var body: some View {
        Text("Hello, World!")
            .onTapGesture {
                showSheet.toggle()
            }
            .sheet(isPresented: $showSheet) {
                LaggyView()
                    .presentationDetents([.medium, .large])
            }
            .offset(y: showSheet ? -300 : 0)
            .animation(.default, value: showSheet)
    }
}

struct LaggyView: View {
    var body: some View {
        Text("hello")
    }
}

struct FirstView_Previews: PreviewProvider {
    static var previews: some View {
        FirstView()
    }
}
like image 389
b.joe Avatar asked Oct 15 '25 21:10

b.joe


1 Answers

The way I solved this was by setting isPresented to false before the sheet could set it.

To do this I set a .coordinateSpace(name: “someName”) on the top level view and wrapped both the view that has the sheet modifier on it and the sheet content in GeometryReaders.

In the sheet content I used the sheet geometry proxy’s frame in the top level named coordinate space and the wrapping view’s geometry frame in the global coordinate space to determine if the offset of the sheet content is greater than the maxY of the global frame. I had to add a bit of a buffer to account for the top portion of the sheet with the drag indicator.


struct OuterView: View {
    var body: some View {
        ContentView()
            .coordinateSpace(name: "someName")
    }
}

struct ContentView: View {
    @State private var isPresented = false
    var body: some View {
        GeometryReader { containingGeometry in
            EmptyView()
                .sheet(isPresented: $isPresented) {
                    GeometryReader { geometry in
                        let frame = geometry.frame(in: .named("someName"))
                        let globalFrame = containingGeometry.frame(in: .global)
                        let buffer = 50.0
                        EmptyView()
                            .onChange(of: frame.origin.y) { newValue in
                                if newValue > globalFrame.maxY + buffer {
                                    withAnimation {
                                        isPresented = false
                                    }
                                }
                            }
                    }
                }
        }
    }
}
like image 139
M L Avatar answered Oct 17 '25 13:10

M L



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!