Close Keyboard & Detect Keyboard Open/Close
Published by @SoNiceInfo at 6/24/2020
I'll show you how to implement closing an open keyboard after entering text and how to detect the keyboard's opening and closing.
Extend UIApplication
"Taping some area to close keyboard" is not derivered by iOS by default. So you need to implement it.
You need to extends UIApplication as it's not provided in SwiftUI's standard functionality.
Define closeKeyboard()
and sendAction
to the selector.
By setting nil to UIResponder.resignFirstResponder
, top of the first responder become nil.
This means no action occured, thus keyboard will be closed.
extension UIApplication {
func closeKeyboard() {
sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
Use function with onTapGesture
To detect user tapping, use onTapGesture
to perform an action.
In this case, onTapGesture
is applied to the yellow background in ZStack
.
With UIApplication.shared.closeKeyboard()
in it, users can close keyboard with tappig yellow background.
//
// ContentView.swift
//
import SwiftUI
struct ContentView: View {
@State var name: String = ""
var body: some View {
ZStack {
Color.yellow
.opacity(0.4)
.edgesIgnoringSafeArea(.all)
// Here is the point
.onTapGesture {
UIApplication.shared.closeKeyboard()
}
VStack {
Text("Result: ") + Text(name)
TextField("Placeholder", text: $name)
.padding()
.border(Color.green, width: CGFloat(2))
}
}
}
}
// Here is the point
extension UIApplication {
func closeKeyboard() {
sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Detect keyboard open/close
Next step, I'll show you how to detect keyboard is opening, closing. onReceive
is usable to detect some event changing from publisher
not only keyboard.
For example, use UIResponder.keyboardDidShowNotification
to detect keyboard opened, use UIResponder.keyboardDidHideNotification
to detect keyboard closed.
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardDidShowNotification)) { _ in
// Write code for keyboard opened.
}.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardDidHideNotification)) { _ in
// Write code for keyboard closed.
}
Here is the publisher around keyboard events.
Opening | UIResponder.keyboardWillShowNotification |
Opened | UIResponder.keyboardDidShowNotification |
Closing | UIResponder.keyboardWillHideNotification |
Closed | UIResponder.keyboardDidHideNotification |
State changing | UIResponder.keyboardWillChangeFrameNotification |
State changed | UIResponder.keyboardDidChangeFrameNotification |
Here is an example program to show "Closed" when keyboard is closed, "Opened" when opened.
//
// ContentView.swift
//
import SwiftUI
struct ContentView: View {
@State var name: String = ""
@State var state: String = "Closed"
var body: some View {
ZStack {
Color.yellow
.opacity(0.4)
.edgesIgnoringSafeArea(.all)
// Here is the point
.onTapGesture {
UIApplication.shared.closeKeyboard()
}
VStack {
Text("Result: ") + Text(name)
TextField("Placeholder", text: $name)
.padding()
.border(Color.green, width: CGFloat(2))
Text("Keyboard: ") + Text(state)
}
}.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardDidShowNotification)) { _ in
self.state = "Opened"
}.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardDidHideNotification)) { _ in
self.state = "Closed"
}
}
}
// Here is the point
extension UIApplication {
func closeKeyboard() {
sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Note
Do not use UIApplication.shared.keyWindow?.endEditing(true)
to close. UIApplication.shared.keyWindow
is deprecated in iOS 13.