问题
I have a TextField in SwiftUI that needs to use a different keyboard depending on the value of a @State variable determined by a SegementedControl() picker.
How can I dismiss the keyboard (like send an endEditing event) when the user taps a different segment? I need to do this because I want to change the keyboard type and if the textField is the responder, the keyboard won't change.
I have this extension:
extension UIApplication {
func endEditing() {
sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
And I can do something like
UIApplication.shared.endEditing()
But I don't know where or how to call this when the user taps a different segment.
I have tried putting a tapGesture on the Picker and the keyboard does dismiss, but the tap does not pass through to the picker so it does not change.
Code snippet here:
@State private var type:String = "name"
. . .
Form {
Section(header: Text("Search Type")) {
Picker("", selection: $type) {
Text("By Name").tag("name")
Text("By AppId").tag("id")
}.pickerStyle(SegmentedPickerStyle())
}
Section(header: Text("Enter search value")) {
TextField(self.searchPlaceHolder, text: $searchValue)
.keyboardType(self.type == "name" ? UIKeyboardType.alphabet : UIKeyboardType.numberPad)
}
}
回答1:
Attach a custom Binding
to the Picker
that calls endEditing()
whenever it is set:
Section(header: Text("Search Type")) {
Picker("", selection: Binding(get: {
self.type
}, set: { (res) in
self.type = res
UIApplication.shared.endEditing()
})) {
Text("By Name").tag("name")
Text("By AppId").tag("id")
}.pickerStyle(SegmentedPickerStyle())
}
回答2:
Update since iOS 13 / iPadOS 13 was released.
Since there is now support for multiple windows in one app you need to loop through the UIWindows and end editing one-by-one.
UIApplication.shared.windows.forEach { $0.endEditing(false) }
回答3:
SwiftUI 2.0
Now it can be done in more elegant way, with .onChange
(actually it can be attached to any view, but at TextField
looks appropriate, by intention)
TextField("Placeholder", text: $searchValue)
.keyboardType(self.type == "name" ? UIKeyboardType.alphabet : UIKeyboardType.numberPad)
.onChange(of: type) { _ in
UIApplication.shared.endEditing() // << here !!
}
SwiftUI 1.0+
There are much similar to above approaches
a) requires import Combine
...
TextField("Placeholder", text: $searchValue)
.keyboardType(self.type == "name" ? UIKeyboardType.alphabet : UIKeyboardType.numberPad)
.onChange(of: type) { _ in
UIApplication.shared.endEditing()
}
.onReceive(Just(type)) { _ in
UIApplication.shared.endEditing() // << here !!
}
b) ... and not
TextField("Placeholder", text: $searchValue)
.keyboardType(self.type == "name" ? UIKeyboardType.alphabet : UIKeyboardType.numberPad)
.onReceive([type].publisher) { _ in
UIApplication.shared.endEditing() // << here !!
}
来源:https://stackoverflow.com/questions/58349955/swiftui-dismiss-keyboard-when-tapping-segmentedcontrol