Reading time: 1 min

This recipe shows how to use fullScreenCover on iOS 13 (or any SwiftUI version, for that matter). It provides a drop-in replacement, fullScreenCoverCompat modifier that does the same trick regardless of what OS version you're running.

The end result looks like this:

preview

Here's the code:

struct FullScreenCoverCompat<CoverContent: View>: ViewModifier {
  @Binding var isPresented: Bool
  let content: () -> CoverContent

  func body(content: Content) -> some View {
    GeometryReader { geo in
      ZStack {
        // this color makes sure that its enclosing ZStack
        // (and the GeometryReader) fill the entire screen,
        // allowing to know its full height
        Color.clear
        content
        ZStack {
          // the color is here for the cover to fill
          // the entire screen regardless of its content
          Color.white
          self.content()
        }
        .offset(y: isPresented ? 0 : geo.size.height)
        // feel free to play around with the animation speeds!
        .animation(.spring())
      }
    }
  }
}

extension View {
  func fullScreenCoverCompat<Content: View>(isPresented: Binding<Bool>,
                                            content: @escaping () -> Content) -> some View {
    self.modifier(FullScreenCoverCompat(isPresented: isPresented,
                                        content: content))
  }
}

Then, you can use it just as easily as the stock modifier:

struct FullScreenCoverCompatTest: View {
  @State private var isPresented = false

  var body: some View {
    Button("Show me") {
      isPresented = true
    }
    .fullScreenCoverCompat(isPresented: $isPresented) {
      ZStack {
        Color.green
        Button("Hide") {
          isPresented = false
        }
        .foregroundColor(.white)
      }
    }
  }
}

While this replacement view doesn't cover the item variant of fullScreenCover, it it easy enough to add it. Let me know if you're interested and we'll do that exericise in the future!

Next Post Previous Post