How can I present an overlay above the keyboard in SwiftUI?

836 Views Asked by At

I have a screen in my app that automatically displays a keyboard when the screen is presented. The screen allows users to enter their mobile number. In order to select a dialling code, the user needs to tap a button which will then trigger the presentation of an overlay.

Problem

The overlay is being presented, but it's showing up behind the currently present keyboard.

Question

How can I make this overlay be the very top view?

There is no way for me to use the zIndex modifier on the keyboard for obvious reasons. I'm wondering if there is a way to make the overlay the top view when it's about to be presented, or if the overlay can be added to the window.

Thanks in advance

1

There are 1 best solutions below

1
On BEST ANSWER

You should probably only have one source of input at any given time — either the keyboard should be presented to enter a number, or the overlay should be presented to pick the dialing code, not both. Here's an example which hides the keyboard when overlay appears, and vice versa. (Keyboard dismissal code from this answer.)

struct ContentView: View {
    @State private var number = ""
    @State private var showingOverlay = false

    var body: some View {
        GeometryReader { proxy in
            ZStack(alignment: .top) {
                // Just here to force ZStack to use the whole screen
                Rectangle()
                    .fill(Color.clear)

                VStack(alignment: .leading) {
                    Button("Select Dialing Code") {
                        UIApplication.shared.endEditing()
                        self.showingOverlay = true
                    }
                    TextField("Enter your number", text: self.$number, onEditingChanged: {
                        if $0 { self.showingOverlay = false }
                    })
                        .keyboardType(.phonePad)
                }

                Overlay(showing: self.$showingOverlay)
                    .frame(height: 400)
                    .offset(x: 0, y: proxy.size.height + (self.showingOverlay ? -300 : 100))
                    .animation(.easeInOut)
            }
        }
    }
}

struct Overlay: View {
    @Binding var showing: Bool

    var body: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 15)
                .fill(Color(.systemGray4))
            Button("Dismiss") {
                self.showing = false
            }
        }
    }
}

extension UIApplication {
    func endEditing() {
        sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}