SwiftUI dismiss keyboard when tapping segmentedControl

こ雲淡風輕ζ 提交于 2021-02-19 01:15:50

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!