I want to click a button and then present a new view like present modally
in UIKit
I have already seen "How to present a new view using sheets", but I don't want to attach it to the main view as a modal sheet.
And I don't want to use NavigationLink
, because I don't want a new view and old view have a navigation relationship.
Thanks for your help...
The first option is to tell the view to dismiss itself using its presentation mode environment key. Any view can read its presentation mode using @Environment(\. presentationMode) , and calling wrappedValue. dismiss() on that will cause the view to be dismissed.
To use a sheet, give it something to show (some text, an image, a custom view, etc), add a Boolean that defines whether the detail view should be showing, then attach it to your main view as a modal sheet. Important: If you're targeting iOS 14 or below, you should use @Environment(\.
You just need a simple sheet
with the ability to dismiss itself:
struct ModalView: View { @Binding var presentedAsModal: Bool var body: some View { Button("dismiss") { self.presentedAsModal = false } } }
And present it like:
struct ContentView: View { @State var presentingModal = false var body: some View { Button("Present") { self.presentingModal = true } .sheet(isPresented: $presentingModal) { ModalView(presentedAsModal: self.$presentingModal) } } }
Note that I passed the presentingModal
to the modal so you can dismiss it from the modal itself, but you can get rid of it.
fullscreen
(Not just visually)You need to access to the ViewController
. So you need some helper containers and environment stuff:
struct ViewControllerHolder { weak var value: UIViewController? } struct ViewControllerKey: EnvironmentKey { static var defaultValue: ViewControllerHolder { return ViewControllerHolder(value: UIApplication.shared.windows.first?.rootViewController) } } extension EnvironmentValues { var viewController: UIViewController? { get { return self[ViewControllerKey.self].value } set { self[ViewControllerKey.self].value = newValue } } }
Then you should use implement this extension:
extension UIViewController { func present<Content: View>(style: UIModalPresentationStyle = .automatic, @ViewBuilder builder: () -> Content) { let toPresent = UIHostingController(rootView: AnyView(EmptyView())) toPresent.modalPresentationStyle = style toPresent.rootView = AnyView( builder() .environment(\.viewController, toPresent) ) NotificationCenter.default.addObserver(forName: Notification.Name(rawValue: "dismissModal"), object: nil, queue: nil) { [weak toPresent] _ in toPresent?.dismiss(animated: true, completion: nil) } self.present(toPresent, animated: true, completion: nil) } }
you can make it fullscreen
like:
struct ContentView: View { @Environment(\.viewController) private var viewControllerHolder: UIViewController? var body: some View { Button("Login") { self.viewControllerHolder?.present(style: .fullScreen) { Text("Main") // Or any other view you like // uncomment and add the below button for dismissing the modal // Button("Cancel") { // NotificationCenter.default.post(name: Notification.Name(rawValue: "dismissModal"), object: nil) // } } } } }
struct ContentView: View { @State private var isPresented = false var body: some View { Button("Show Modal with full screen") { self.isPresented.toggle() } .fullScreenCover(isPresented: $isPresented, content: FullScreenModalView.init) } }
struct FullScreenModalView: View { @Environment(\.presentationMode) var presentationMode var body: some View { VStack { Text("This is a modal view") } .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color.red) .edgesIgnoringSafeArea(.all) .onTapGesture { presentationMode.wrappedValue.dismiss() } } }
Hope this answer can help you all! Comment below about your result.
Ref: This Link
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With