Search code examples
swiftswiftuifullscreen

SwiftUI: Full screen View over NavigationBar and TabBar


I'm trying to add a full screen View over my app in SwiftUI. The purpose of this is to have a "shade" that fades in that will darken the screen and bring focus to a custom pop-up, disabling content in the background. See below for a visual example:

What I've gotWhat I want

The View that I'm trying to add this shade over is embedded in a complex NavigationView stack (several layers deep, accessed via a NavigationLink) and also has a visible TabBar. So far I've tried embedding the NavigationView in a ZStack and adding a Rectangle() on top but to no avail, the NavigationBar and TabBar still sit on top of this view. I've also tried using using the .zIndex() modifier but this seems to have done nothing.

Any help is much appreciated,

Thanks


Solution

  • You do not need work on zIndex, because you cover the all screen! Even you do not need work on disable your current View for using PopUp, because again PopUp is already on top layer. zIndex would be helpful when you did not cover the screen, here is a way:

    struct ContentView: View {
        
        @State private var isPresented: Bool = Bool()
        
        var body: some View {
            
            NavigationView {
                
                VStack {
                    
                    Button("Show Custom PopUp View") { isPresented.toggle() }
    
                }
                .navigationTitle("Navigation Title")
                
            }
            .customPopupView(isPresented: $isPresented, popupView: { popupView })
            
        }
        
        var popupView: some View {
            
            RoundedRectangle(cornerRadius: 20.0)
                .fill(Color.white)
                .frame(width: 300.0, height: 200.0)
                .overlay(
                    
                    Image(systemName: "xmark").resizable().frame(width: 10.0, height: 10.0)
                        .foregroundColor(Color.black)
                        .padding(5.0)
                        .background(Color.red)
                        .clipShape(Circle())
                        .padding()
                        .onTapGesture { isPresented.toggle() }
                    
                    , alignment: .topLeading)
                
                .overlay(Text("Custom PopUp View!"))
                .transition(AnyTransition.scale)
                .shadow(radius: 10.0)
            
        }
    }
    
    
    struct CustomPopupView<Content, PopupView>: View where Content: View, PopupView: View {
        
        @Binding var isPresented: Bool
        @ViewBuilder let content: () -> Content
        @ViewBuilder let popupView: () -> PopupView
        let backgroundColor: Color
        let animation: Animation?
        
        var body: some View {
            
            content()
                .animation(nil, value: isPresented)
                .overlay(isPresented ? backgroundColor.ignoresSafeArea() : nil)
                .overlay(isPresented ? popupView() : nil)
                .animation(animation, value: isPresented)
            
        }
    }
    
    extension View {
        func customPopupView<PopupView>(isPresented: Binding<Bool>, popupView: @escaping () -> PopupView, backgroundColor: Color = .black.opacity(0.7), animation: Animation? = .default) -> some View where PopupView: View {
            return CustomPopupView(isPresented: isPresented, content: { self }, popupView: popupView, backgroundColor: backgroundColor, animation: animation)
        }
    }
    

    enter image description here