I’m looking for a working answer for this downside for a very long time however can not seem to get any options on SO working in my case. SwiftUI’s ‘.alert’ modifier appears to current itself on prime of all of the views, however the customization of the alert components is so restricted attributable to which I needed to create a customized alert. My alert comprises icons and styled buttons.
My app is advanced, so sharing a brief pattern working instance. The app presents a MainView and there’ll all the time be a sheet over it whose peak may be adjusted (typically full display screen cowl as an alternative of sheet). Alerts may be introduced by MainView and by any of the sheet views. In any case, I need alert to be all the time on prime of sheet view (or full display screen cowl)
Right here I attempted presenting an alert (take into account Coloration.black.opacity.. as an alert in my code under) in 2 other ways.
- A technique is utilizing ZStack in ContentView and even in MainView. In each
the circumstances, the AlertView opens behind SheetView and does not cowl
SheetView. - Second method is utilizing an AlertViewModifier in SheetView.
With this, the alert will get introduced throughout the SheetView (as an alternative of
over SheetView) such that I’m nonetheless in a position to work together with the
MainView and in addition in a position to regulate peak of SheetView.
Pattern code:
import SwiftUI
class SampleViewModel: ObservableObject {
@Printed var showSheet = false
@Printed var panelDetent = PresentationDetent.medium
@Printed var showZStackAlert: Bool = false
}
struct ContentViewA: View {
@StateObject var viewModel: SampleViewModel = .init()
@State non-public var showSheet: Bool = false
var physique: some View {
NavigationStack {
ZStack {
if viewModel.showZStackAlert {
AlertView()
}
MainView()
}
}
.environmentObject(viewModel)
}
}
/// Presenting customized alert from foremost ContentView
struct AlertView: View {
var physique: some View {
VStack {
Coloration.black.opacity(0.5).edgesIgnoringSafeArea(.all)
}
}
}
struct MainView: View {
@EnvironmentObject var viewModel: SampleViewModel
@State non-public var showSheet: Bool = false
var physique: some View {
ZStack {
// if viewModel.showZStackAlert {
// AlertView()
// }
//
VStack {
Textual content("That is foremost view with all the time one sheet displayed")
}
}
.onAppear {
self.showSheet = true
}
.sheet(isPresented: $showSheet) {
SheetView().environmentObject(viewModel)
}
// Extra sheets
//.sheet(isPresented: $showSheetA) {
//SheetViewA().environmentObject(viewModel)
//}
}
}
struct SheetView: View {
@EnvironmentObject var viewModel: SampleViewModel
@Surroundings(.presentationMode) non-public var presentationMode
@State non-public var showAlert: Bool = false
var physique: some View {
NavigationStack {
ZStack {
Coloration.mint.opacity(0.1).edgesIgnoringSafeArea(.all)
VStack {
Button {
viewModel.showZStackAlert = true
// self.showAlert = true
} label: {
Textual content("Faucet me to open alert")
}
}
}
}
.presentationDetents([.medium, .large], choice: $viewModel.panelDetent)
.interactiveDismissDisabled(true)
.presentationBackgroundInteraction(.enabled)
.alertView(isPresented: $showAlert)
}
}
/// Presenting customized alert utilizing Alert View Modifier
struct AlertViewModifier: ViewModifier {
@Binding var isPresented: Bool
init(isPresented: Binding) {
self._isPresented = isPresented
}
func physique(content material: Content material) -> some View {
content material
.animation(nil, worth: self.$isPresented.wrappedValue)
.overlay(self.$isPresented.wrappedValue ? Coloration.black.opacity(0.5) : nil)
.overlay(self.$isPresented.wrappedValue ? alertContent() : nil)
.animation(.default, worth: self.$isPresented.wrappedValue)
}
@ViewBuilder
non-public func alertContent() -> some View {
GeometryReader { geometry in
if self.$isPresented.wrappedValue {
VStack {
/// Contents of alert view
}
.fixedSize(horizontal: false, vertical: true)
.place(x: geometry.measurement.width/2, y: geometry.measurement.peak/2)
.body(minWidth: 350.0, maxWidth: 350.0)
}
}
}
}
extension View {
func alertView(isPresented: Binding) -> some View {
return modifier(AlertViewModifier(isPresented: isPresented))
}
}
How can I current AlertView all the time on prime of sheet view?