0

I would like to reproduce inside a ZStack the height effect that you see when a modal is presented in iOS 13:

The background is slightly transparent and becomes greyish with a blur effect.

The idea would be to create a view that seems to be floating above the elements below inside a ZStack.

Mycroft Canner
  • 1,828
  • 1
  • 11
  • 24

1 Answers1

0

You can have a ZStack with a view that is conditionally displayed depending on a @State variable. The variable will also determine the .blur amount on the underlying view and whether or not a transparent gray view is displayed in between (which makes the background look grayed out). I made an example to illustrate:

struct ContentView: View {
    @State var modalIsPresented = false
    @State var alertIsPresented = false
    @State var customAlertIsPresented = false
    var body: some View {
        ZStack {
            Text("Test!!!")

            VStack {
                Spacer()
                Text("Lorem ipsum dolor sit amet")
                Spacer()
                Text("Lorem ipsum dolor sit amet")
                Image(systemName: "star")
                Button(action: {
                    self.modalIsPresented = true
                }) {
                    Text("Present an actual modal")
                }
                Button(action: {
                    self.alertIsPresented = true
                }) {
                    Text("Present an actual alert")
                }
                Button(action: {
                    withAnimation {
                        self.customAlertIsPresented = true
                    }
                }) {
                    Text("Present your custom alert")
                }
            }
            .blur(radius: self.customAlertIsPresented ? 3 : 0)
            .animation(.easeOut)
            if customAlertIsPresented {
                Rectangle()
                    .background(Color.black)
                    .opacity(0.3)
                    .edgesIgnoringSafeArea(.all)
                    .animation(.easeIn)
            }
            if customAlertIsPresented {
                CustomAlert(isPresented: $customAlertIsPresented).frame(width: 300)
                    .background(Color.white)
                    .animation(.easeIn)
                    .cornerRadius(10)
                    .shadow(radius: 10)
            }
        }.sheet(isPresented: $modalIsPresented) {
            Text("This is what an actual modal looks like")
        }.alert(isPresented: $alertIsPresented) {
            Alert(title: Text("This is what an alert looks like"))
        }
    }
}

struct CustomAlert: View {
    @Binding var isPresented: Bool
    var body: some View {
        VStack {
            Text("This is my custom alert").padding()
            Divider()
            Button(action: {
                self.isPresented = false
            }) {
                HStack {
                    Spacer()
                    Text("Dismiss")
                    Spacer()
                }
            }.padding([.top, .bottom], 10)
        }
    }
}

I added some animations to make the transition smoother. You can adjust things like the .blur, .opacity, and various .animations to customize it took look just the way you want. Here's what my example looks like:

Prior to showing alertAfter showing the alert

RPatel99
  • 7,448
  • 2
  • 37
  • 45