SwiftUI Tips:如何隐藏键盘
首先需要引入一个方法调用系统接口隐藏键盘:
extension UIApplication {
func endEditing() {
sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
// 也可以把辅助方法添加到 View 上
extension View {
func endEditing() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
// 还有一种实现是通过获取 keyWindow 调用到 UIView 的 endEditing
func endEditing() {
UIApplication.shared.windows.filter {$0.isKeyWindow}.first?.endEditing(true)
}
}
隐藏最简单的处理方式就是在键盘按 return 的时候隐藏键盘:
struct ContentView: View {
@State private var name: String = ""
var body: some View {
TextField("名字:", text: $name)
.onSubmit {
UIApplication.shared.endEditing()
}
}
}
对键盘的常见处理方式还有点击空白处隐藏键盘。可以通过添加 Tap 手势来达到目的。
var body: some View {
ZStack {
Color.white
.onTapGesture {
UIApplication.shared.endEditing()
}
TextField("名字:", text: $name)
.onSubmit {
UIApplication.shared.endEditing()
}
}
}
如果点击隐藏键盘要全局处理,也可以把 TapGesture 直接加在 window 上:
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.onAppear(perform: UIApplication.shared.addTapGestureRecognizer)
}
}
}
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)
}
}
extension UIApplication: UIGestureRecognizerDelegate {
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true // set to `false` if you don't want to detect tap during other gestures
}
}
在 iOS 15 中 SwiftUI 引入了@FocusState
来控制焦点,所以官方推荐的一个方案是通过设置焦点的值来控制键盘的弹出与隐藏。
老实说系统推荐的焦点控制有一种清澈的愚蠢。
struct FocusStateView: View {
@State private var name: String = ""
@FocusState private var focusedField: Bool
var body: some View {
VStack {
TextField("名字", text: $name)
.focused($focusedField)
HStack {
Button("focus") {
focusedField = true
}
Button("dismiss") {
focusedField = false
}
}
}
.padding()
}
}
还有一种常见的键盘处理方案是在键盘上面添加一个工具栏,增加一个完成按钮。在 SwiftUI 中也可以很容易的实现这个功能。
struct ContentView: View {
@State private var name: String = ""
var body: some View {
VStack {
TextField("名字:", text: $name)
.padding()
}
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
Spacer()
Button("完成") {
UIApplication.shared.endEditing()
}
}
}
}
}