iOS 14+
當(dāng)用戶輸入完畢,通過(guò)點(diǎn)擊空白處,快捷實(shí)現(xiàn)鍵盤收起;同時(shí)也不影響其他正常的交互操作。這個(gè)需求的場(chǎng)景應(yīng)該非常常見(jiàn),大部分涉及鍵盤輸入的時(shí)候,都會(huì)需要實(shí)現(xiàn)上述的功能。
先回顧一下 UIKit 中隱藏鍵盤的方法,本質(zhì)上是需要獲取到承載鍵盤的視圖:
// 方法一:
textField.resignFirstResponder()
// 方法二:
view.endEditing(true)
那么其實(shí)對(duì)于 SwiftUI 來(lái)說(shuō),雖然沒(méi)有之前 View 的概念了,但是同樣可以獲取到整個(gè) App 的 window,從而調(diào)用 endEditing。為了方便,我們直接給 UIApplication 增加 Extension:
extension UIApplication {
? ? func addTapGestureRecognizer() {
? ? ? ? guard let window = windows.first else { return }
? ? ? ? let tapGesture = UITapGestureRecognizer(target: window, action: #selector(UIView.endEditing))
? ? ? ? tapGesture.requiresExclusiveTouchType = false
? ? ? ? tapGesture.cancelsTouchesInView = false
? ? ? ? tapGesture.delegate = self
? ? ? ? window.addGestureRecognizer(tapGesture)
? ? }
}
需要注意的是,下面兩個(gè)參數(shù)需要配置正確:
requiresExclusiveTouchType:默認(rèn)為 true。這個(gè)屬性是指是否允許多種手勢(shì)輸入,這里的多種包含觸摸、遙控器、觸控筆等,所以可以配置成 false(當(dāng)然不配置也不會(huì)有太大影響)
cancelsTouchesInView:默認(rèn)為 true。這里設(shè)置為 false,主要為了不影響其他手勢(shì)的識(shí)別。當(dāng)前的 tap 手勢(shì)被識(shí)別出來(lái)之后,也不會(huì)觸發(fā) UITouch 的 cancel 方法,因此就不會(huì)中斷 UITouch 的傳遞。
當(dāng)然,為了不影響其他手勢(shì)的識(shí)別,還需要實(shí)現(xiàn)下面這個(gè)方法:
extension UIApplication: UIGestureRecognizerDelegate {
? ? public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
? ? ? ? return true // 可以同時(shí)響應(yīng)多個(gè)手勢(shì)
? ? }
}
最后我們只需要在整個(gè) App 初始化時(shí)加上手勢(shì)識(shí)別就可以了:
@main
struct MyApp: App {
? ? var body: some Scene {
? ? ? ? WindowGroup {
? ? ? ? ? ? ContentView()
? ? ? ? ? ? ? ? .onAppear(perform: UIApplication.shared.addTapGestureRecognizer)
? ? ? ? }
? ? }
}