Home > Enterprise >  Change size of modal sheet from half to full animated in SwiftUI
Change size of modal sheet from half to full animated in SwiftUI

Time:09-22

I would like a certain view to start as a half-screen sheet, but when it's done with some loading, it should transform into a full-screen sheet.

So in UIKit my solution would be that:

let vc = UIViewController()
vc.view.backgroundColor = .red
vc.sheetPresentationController?.detents = [.medium(), .large()]
self.present(vc, animated: true)

DispatchQueue.main.asyncAfter(deadline: .now()   .seconds(1)) {
    vc.sheetPresentationController?.animateChanges {
        vc.sheetPresentationController?.selectedDetentIdentifier = .large
    }
}

That works fine in UIKit... but is this also somehow possible in SwiftUI?

Something similar in SwiftUI could look like the following:

    struct ContentView: View {
    @State var showSheet = false
    
    var body: some View {
        Button {
            showSheet = true
        } label: {
            Text("Show-Sheet")
        }
        .sheet(isPresented: $showSheet, content: {
            SheetView()
        })
    }
}

struct SheetView: View {
    @State var showFullSheet = false
    
    var body: some View {
        Button {
            withAnimation {
                showFullSheet.toggle()
            }
        } label: {
            Text("Toggle")
        }
        .presentationDetents(showFullSheet ? [.large] : [.medium, .large])
    }
}

This basically works, but the problem is that the transition between half and full is NOT animated. I'd need it animated though. Is this somehow solvable in SwiftUI? Cause I guess wrapping my presented view in a UIViewController that then hosts my existing SwiftUI View would not be an option, as the presentation part would still be done by swift-ui, right?

CodePudding user response:

For that use selection binding of presentationDetents(_:selection:) .

struct SheetView: View {

    @State var selectedDetent: PresentationDetent = .medium
    
    var body: some View {
        Button {
            selectedDetent = selectedDetent == .large ? .medium : .large
        } label: {
            Text("Toggle")
        }
        .presentationDetents(selectedDetent == .large ? [.large] : [.medium, .large], selection: $selectedDetent)
    }
}

CodePudding user response:

Could it just be that you're missing withAnimation from your showSheet = true

  • Related