Modular Alert In SwiftUI
In this article, We will explore how to implement a Modular Custom Alert Dialog in SwiftUI
Before proceeding, please consider subscribing to our YOUTUBE CHANNEL
It gives us a lot of motivation to produce high-quality content for you guys.
if you are interested in watching the video tutorial, Check out below.
Let's start by creating the CustomAlertDialog
script and add the required variables.
import SwiftUI
struct CustomAlertDialog: View {
var title: String
var message: String
var positiveButtonTitle: String? = "OK"
var negativeButtonTitle: String? = "Cancel"
private var positiveButtonAction: (() -> ())? = {}
private var negativeButtonAction: (() -> ())? = {}
private var isShowVerticalButtons = false
private let verticalButtonHeight: CGFloat = 80
init(title: String, message: String, positiveButtonTitle: String? = "OK", negativeButtonTitle: String? = "Cancel", positiveButtonAction: ( () -> Void)? = nil, negativeButtonAction: ( () -> Void)? = nil, isShowVerticalButtons: Bool = false) {
self.title = title
self.message = message
self.positiveButtonTitle = positiveButtonTitle
self.negativeButtonTitle = negativeButtonTitle
self.positiveButtonAction = positiveButtonAction
self.negativeButtonAction = negativeButtonAction
self.isShowVerticalButtons = isShowVerticalButtons
}
var body: some View {
}
}
I have added a HeaderView
and a FooterView
. As of now, they are just empty views which we’ll fill soon
import SwiftUI
struct CustomAlertDialog: View {
var title: String
var message: String
var positiveButtonTitle: String? = "OK"
var negativeButtonTitle: String? = "Cancel"
private var positiveButtonAction: (() -> ())? = {}
private var negativeButtonAction: (() -> ())? = {}
private var isShowVerticalButtons = false
private let verticalButtonHeight: CGFloat = 80
init(title: String, message: String, positiveButtonTitle: String? = "OK", negativeButtonTitle: String? = "Cancel", positiveButtonAction: ( () -> Void)? = nil, negativeButtonAction: ( () -> Void)? = nil, isShowVerticalButtons: Bool = false) {
self.title = title
self.message = message
self.positiveButtonTitle = positiveButtonTitle
self.negativeButtonTitle = negativeButtonTitle
self.positiveButtonAction = positiveButtonAction
self.negativeButtonAction = negativeButtonAction
self.isShowVerticalButtons = isShowVerticalButtons
}
var body: some View {
ZStack {
Color.black.opacity(0.75)
.ignoresSafeArea()
VStack(spacing: 0, content: {
HeaderView()
FooterView()
})
.frame(width: 270, height: isShowVerticalButtons ? 220 : 150)
.background(Color.white)
.cornerRadius(4)
}
.zIndex(2)
}
@ViewBuilder
private func HeaderView() -> some View {
}
@ViewBuilder
private func FooterView() -> some View {
}
}
The header view consists of a title, a message, and a divider. You can edit your dialog UI as you want.
FooterView
consists of a two-button layout which will be changed to vertical or horizontal based on the boolean modifier.
@ViewBuilder
private func HeaderView() -> some View {
Text(title)
.font(.system(size: 16, weight: .bold))
.foregroundColor(.black)
.multilineTextAlignment(.center)
.frame(height: 25)
.padding(.top, 16)
.padding(.bottom, 8)
.padding(.horizontal, 16)
Text(message)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
.font(.system(size: 14))
.foregroundColor(.black)
.multilineTextAlignment(.center)
.padding(.horizontal, 16)
.padding(.bottom, 16)
.minimumScaleFactor(0.5)
Divider()
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 0.5)
.padding(.all, 0)
}
@ViewBuilder
private func FooterView() -> some View {
let buttonLayout = isShowVerticalButtons ? AnyLayout(VStackLayout()) : AnyLayout(HStackLayout())
buttonLayout {
if isShowVerticalButtons {
Spacer()
}
Button(action: {
negativeButtonAction?()
}, label: {
Text(negativeButtonTitle ?? "")
.font(.system(size: 16, weight: .bold))
.foregroundColor(.black)
.multilineTextAlignment(.center)
.padding()
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
})
if isShowVerticalButtons {
Spacer()
Divider()
Spacer()
} else {
Divider()
.frame(minWidth: 0, maxWidth: 0.5, minHeight: 0, maxHeight: .infinity)
}
Button {
positiveButtonAction?()
} label: {
Text(positiveButtonTitle ?? "")
.font(.system(size: 16, weight: .bold))
.foregroundColor(.pink)
.multilineTextAlignment(.center)
.padding(15)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
}
if isShowVerticalButtons {
Spacer()
}
}.padding([.horizontal, .bottom], 0)
}
We’ll use the below code to create custom modifiers.
extension CustomAlertDialog {
func makeButtonsVertical(_ isVertical: Bool) -> Self {
var alert = self
alert.isShowVerticalButtons = isVertical
return alert
}
func onPositiveButtonTap(_ positiveButtonAction: (() -> ())?) -> Self {
var alert = self
alert.positiveButtonAction = positiveButtonAction
return alert
}
func onNegativeButtonTap(_ negativeButtonAction: (() -> ())?) -> Self {
var alert = self
alert.negativeButtonAction = negativeButtonAction
return alert
}
}
Below is an example of the View
CustomAlertDialog(title: "Error", message: "Something went wrong, Please try again later..", positiveButtonTitle: "OK", negativeButtonTitle: "Cancel")
.makeButtonsVertical(false)
.onNegativeButtonTap {
presentAlert.toggle()
}
.onPositiveButtonTap {
presentAlert.toggle()
}
That's it you should be able to see the dialog now
Once again Thanks for stopping by.
Do check out our YOUTUBE CHANNEL
Social Handles
Instagram : https://www.instagram.com/mobileappsacademy/
Twitter : https://twitter.com/MobileAppsAcdmy
LinkedIn : https://www.linkedin.com/company/mobile-apps-academy/