How to dismiss a custom modal in SwiftUI

Create an "OnTapOutside" listener on dismiss a custom modal

If you want to show a custom modal in your application, and don't want to use the default .sheet modifier, you can easily create an onTapOutside listener to dismiss your modal.

Create a showModal state 

Let's start by creating our state showModal that will toggle between true or false. The initial value will be set to false, meaning the modal will not be shown by default.

@State var showModal: Bool = false

..

Create a ZStack 

Then, let's create a ZStack with a greyed-out Rectangle(). On top of the rectangle, let's show the modal. In my case, I created the modal in another file called SignInView and simply called it after the Rectangle(). 

Add the .edgesIgnoringSafeArea(.all) if you want the rectangle to go over the screen's safe area.

ZStack {
    Rectangle()
		.foregroundColor(Color.black.opacity(0.5))
		.edgesIgnoringSafeArea(.all)

		SignInView()
}

..

Add the onTapGesture 

The important part is to add an onTapGesture listener on the rectangle. When the user taps on it (the area outside the modal), we want to dismiss the modal. Therefore, we can simply set the showModal variable to false.

.onTapGesture {
		showModal = false
}

..

Add a button to show the modal 

Remember to add your button to toggle the showModal state to true so that you can show the modal when the user taps on it.

Button(action: {
	showModal = true
}) {
	Text("Sign in")
}

..

Output:

Finally, wrap the entire ZStack in an if statement so that we show the modal and the Rectangle() when the showModal variable is set to true. The final code will look like something like this:

Button(action: {
	showModal = true
}) {
	Text("Sign in")
}

if showModal {
	ZStack {
	    Rectangle()
		 .foregroundColor(Color.black.opacity(0.5))
		.edgesIgnoringSafeArea(.all)
		.onTapGesture {
				showModal = false
	         }

			SigninView()
	}
}

..

Comments