问题
I didn't find any link or guide to change the "return" key to "done" when keyboard open for TextField in SwiftUI.
Is it possible now without customising UITextField?
回答1:
The best way I found was to just add the package Introspect to your project.
After doing so add in import Introspect anywhere in your project files.
Then add one of their View Modifiers to your Textfield to achieve what you want. I believe this is what you want though ⤵
.introspectTextField { textfield in
textfield.returnKeyType = .done
}
What Does Introspect Do?
It exposes UIKit to be used in Swift. So that Textfield object you see above there has access to all UITextfield functionality! This is a package though so be aware it could break in the future but for now this is a good option.
It's just nice because it saves you from making your own UIKit wrapper for every View 😊
回答2:
If somebody is looking for wrapping UITextField in UIViewRepresentable then I have some code to share:
struct CustomTextField: UIViewRepresentable {
let tag: Int
let placeholder: String
let keyboardType: UIKeyboardType
let returnVal: UIReturnKeyType
@Binding var text: String
@Binding var activeFieldTag: Int?
var totalFields: Int = 0
@Binding var isSecureTextEntry: Bool
var textColor: UIColor = .pureWhite
var font: UIFont = .nexaBold13
var placeholderTextColor: UIColor = .pureWhite
var placeholderFont: UIFont = .nexaLight13
var onEditingChanged: (Bool) -> Void = { _ in }
var lastActiveFieldTag: Int? {
// Return, if no active field
// (It also means textFieldShouldReturn not called yet OR called for last field)
guard let activeFieldTag = activeFieldTag else {
return nil
}
// Return previous field
if activeFieldTag > 0 {
return activeFieldTag - 1
}
// Return, if no previous field
return nil
}
func makeUIView(context: Context) -> UITextField {
let textField = UITextField(frame: .zero)
textField.keyboardType = self.keyboardType
textField.returnKeyType = self.returnVal
textField.tag = self.tag
textField.textColor = textColor
textField.font = font
textField.attributedPlaceholder = NSAttributedString(
string: self.placeholder,
attributes: [
NSAttributedString.Key.foregroundColor: placeholderTextColor,
NSAttributedString.Key.font: placeholderFont,
]
)
textField.delegate = context.coordinator
textField.autocorrectionType = .no
textField.isSecureTextEntry = isSecureTextEntry
return textField
}
func updateUIView(_ textField: UITextField, context: Context) {
if textField.text != self.text {
textField.text = self.text
}
handleFirstResponder(textField)
if textField.isSecureTextEntry != isSecureTextEntry {
textField.isSecureTextEntry = isSecureTextEntry
}
}
func handleFirstResponder(_ textField: UITextField) {
// return if field is neither active nor last-active
if tag != lastActiveFieldTag && tag != activeFieldTag {
return
}
// return if field is already active
if lastActiveFieldTag == activeFieldTag {
return
}
// It creates problem in UI when we press the next button too fast and continuously on keyboard
// // Remove focus from last active field
// if lastActiveFieldTag == tag {
// uiView.removeFocus()
// return
// }
// Give focus to active field
if activeFieldTag == tag {
textField.focus()
return
}
}
// Its called when pressing Next button on the keyboard
// See textFieldShouldReturn
func updateNextTag() {
// There is no next field so set activeFieldTag to nil
if tag + 1 == totalFields {
activeFieldTag = nil
} else {
// Set next field tag as active
activeFieldTag = tag + 1
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UITextFieldDelegate {
var parent: CustomTextField
init(_ textField: CustomTextField) {
self.parent = textField
}
func updatefocus(textfield: UITextField) {
textfield.focus()
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// Give focus to next field
parent.updateNextTag()
parent.text = textField.text ?? ""
// If there is no next active field then dismiss the keyboard
if parent.activeFieldTag == nil {
DispatchQueue.main.async {
textField.removeFocus()
}
}
return true
}
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
DispatchQueue.main.async {
// To enable user to click on any textField while another is active
self.parent.activeFieldTag = self.parent.tag
self.parent.onEditingChanged(true)
}
return true
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
self.parent.text = textField.text ?? ""
DispatchQueue.main.async {
self.parent.onEditingChanged(false)
}
return true
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let text = textField.text, let rangeExp = Range(range, in: text) {
self.parent.text = text.replacingCharacters(in: rangeExp, with: string)
}
return true
}
}
}
回答3:
To get the go button on the keyboard. Try changing the keyboardtype to .webSearch.
// Tested on Xcode 12 beta 2 and iOS 14
.keyboardType(.webSearch)
来源:https://stackoverflow.com/questions/60008549/is-it-possible-to-change-return-key-to-done-on-keyboard-in-2020-with-swiftui