May 11, 2024 iOS

How to hide keyboard when using SwiftUI?

In SwiftUI, you can hide the keyboard by resigning the first responder status of the current text field. There are a few ways to accomplish this:

1.Using UIApplication.shared.sendAction(_:to:from:for:): You can use the UIApplication method sendAction(_:to:from:for:) to send the resignFirstResponder action to the current responder. Here’s how you can use it:

UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)

This line of code will hide the keyboard regardless of the currently focused text field.

2.Using endEditing(_:) on UIView: You can extend View to provide a function that ends editing on the UIView. Here’s an example:

extension View {
    func endEditing(_ force: Bool) {
        UIApplication.shared.windows.forEach { $0.endEditing(force) }
    }
}

You can then call endEditing(_:) on any view to hide the keyboard:

struct ContentView: View {
    @State private var text: String = ""
    
    var body: some View {
        TextField("Enter text", text: $text)
            .padding()
            .onTapGesture {
                self.endEditing(true)
            }
    }
}

In this example, tapping anywhere on the view will hide the keyboard.

    3.Using onTapGesture with a Clear Overlay: You can overlay the entire screen with an invisible view that detects taps and hides the keyboard. Here’s an example:

    struct ContentView: View {
        @State private var text: String = ""
        
        var body: some View {
            ZStack {
                TextField("Enter text", text: $text)
                    .padding()
                
                Color.clear
                    .onTapGesture {
                        self.endEditing(true)
                    }
            }
        }
    }
    

    In this example, tapping anywhere on the screen outside the text field will hide the keyboard.

    4.Hide Keyboard When Tapped Outside the TextField: To close the keyboard when the user taps outside the TextField, you can create a full-screen white view with a tap action. This action will trigger the endEditing() function:

    struct Background<Content: View>: View {
        private var content: Content
    
        init(@ViewBuilder content: @escaping () -> Content) {
            self.content = content()
        }
    
        var body: some View {
            Color.white
                .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
                .overlay(content)
        }
    }
    
    struct ContentView: View {
        @State private var name: String = ""
    
        var body: some View {
            Background {
                VStack {
                    Text("Hello \(self.name)")
                    TextField("Name...", text: self.$name) {
                        self.endEditing()
                    }
                }
            }
            .onTapGesture {
                self.endEditing()
            }
        }
    
        private func endEditing() {
            UIApplication.shared.endEditing()
        }
    }