SwiftUI: fullScreenCover with no animation?

Viewed 2663

I have this view:

struct TheFullCover: View {
    
    @State var showModal = false
    
    var body: some View {
        
        
        Button(action: {
            showModal.toggle()
        }) {
            Text("Show Modal")
                .padding()
                .foregroundColor(.blue)
            
        }
        .background(Color(.white))
        .overlay(
            RoundedRectangle(cornerRadius: 10)
                .stroke(.red, lineWidth:1)
        )
        .fullScreenCover(isPresented: $showModal, onDismiss: {
            
        }, content: {
            VStack {
                Text("Here I am")
                TheFullCover()
            }
        })
        
    }
    
    
}

Every time I press the Button, the modal screen comes up fullscreen. All works great.

Question:

How do I disable the slide up animation? I want the view to be presented immediately fullscreen without animating to it.

Is there a way to do that?

4 Answers

A possible solution is to disable views animation completely (and then, if needed, enable again in .onAppear of presenting content), like

    Button(action: {
        UIView.setAnimationsEnabled(false)    // << here !!
        showModal.toggle()
    }) {

and then

    }, content: {
        VStack {
            Text("Here I am")
            TheFullCover()
        }
        .onAppear {
            UIView.setAnimationsEnabled(true)    // << here !!
        }
    })

Tested with Xcode 13 / iOS 15

AFAIK the proper to do it as of today is using transaction https://developer.apple.com/documentation/swiftui/transaction

var transaction = Transaction()
transaction.disablesAnimations = true
withTransaction(transaction) {
   showModal.toggle()
}

I also created a handy extension for this:

extension View {
    func withoutAnimation(action: @escaping () -> Void) {
        var transaction = Transaction()
        transaction.disablesAnimations = true
        withTransaction(transaction) {
            action()
        }
    }
}

which can be used like this:

withoutAnimation {
    // do your thing
}

At the moment, I find it easier to use UIKit for presentation in SwiftUI.

someView
  .onChange(of: isPresented) { _ in
    if isPresented {
      let vc = UIHostingController(rootView: MyView())
      vc.modalPresentationStyle = .overFullScreen
      UIApplication.shared.rootVC?.present(vc, animated: false)
    } else {
      UIApplication.shared.rootVC?.dismiss(animated: false)
    }
  }
.fullScreenCover(isPresented: isPresented) {
    content()
        .background(TransparentBackground())
}
.transaction({ transaction in
    transaction.disablesAnimations = true
})

this should work, based on @asamoylenko's answer

Related