是否可以使用 SwiftUI 将键盘上的“返回”键更改为“完成”?
Posted
技术标签:
【中文标题】是否可以使用 SwiftUI 将键盘上的“返回”键更改为“完成”?【英文标题】:Is it possible to change "return" key to "done" on keyboard with SwiftUI? 【发布时间】:2020-01-31 17:20:37 【问题描述】:在 SwiftUI 中为 TextField 打开键盘时,我没有找到任何链接或指南来将“返回”键更改为“完成”。
现在可以不自定义 UITextField 吗?
【问题讨论】:
这能回答你的问题吗? Change 'Return' button function to 'Done' in swift in UITextView 不,他们正在使用 UIKit,我正在寻找 SwiftUI 的答案 我正在寻找 ***.com/questions/58121756/… 但没有 UIKit。 跳到下面 Ty Irvine 的回答,我认为是迄今为止最简单的解决方案 【参考方案1】:ios 15
您可以使用一个名为 submitLabel
的简单修饰符更改每个 textField
的返回键,该修饰符采用返回键类型:
来自 WWDC21 的图片
此外,如您所见,您可以使用回调来处理返回键按下操作,就像 .onSubmit
修饰符可以访问的旧 textFieldShouldReturn
函数一样。
⚠️ 似乎 Xcode 13 beta 1 中存在一个错误,导致此修饰符在某些情况下无法正常工作。
【讨论】:
它对你有用吗?它不适合我,我想知道是否有错误或什么...... 你检查过 iOS 15 吗? 好的,我只是发现它在工作表中不起作用。没有工作表,它工作正常。【参考方案2】:更新
这不再是一个好的解决方案。在 iOS 15 中,您现在可以添加 .submitLabel(.done)
修饰符。有关详细信息,请参阅 Mojtaba 的回答。
旧答案
我发现最好的方法是将包 Introspect 添加到您的项目中。
这样做后,在项目文件的任何位置添加import Introspect
。
然后将他们的视图修饰符之一添加到您的Textfield
以实现您想要的。我相信这就是你想要的 ⤵
.introspectTextField textfield in
textfield.returnKeyType = .done
内省是做什么的?
它公开了 UIKit 以在 SwiftUI 中使用。因此,您在上面看到的 Textfield
对象可以访问所有 UITextfield
功能!虽然这是一个软件包,但请注意它可能会在未来损坏,但目前这是一个不错的选择。
这很好,因为它使您不必为每个视图制作自己的 UIKit 包装器?
【讨论】:
这是一个很棒的 pod,谢谢分享。我真的不喜欢这样的解决方法,我认为这是一种天才的方法,直到这些东西可以更自然地在 SwiftUI 中访问。 这应该被选为正确答案。【参考方案3】:如果有人想在 UIViewRepresentable 中包装 UITextField,那么我有一些代码可以分享:
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
【讨论】:
为什么我收到错误消息说Type 'UIColor' has no member 'pureWhite'
并且“UITextField”类型的值没有成员“焦点”?有什么变化【参考方案4】:
获取键盘上的go
按钮。尝试将键盘类型更改为 .webSearch。
// 在 Xcode 12 beta 2 和 iOS 14 上测试
.keyboardType(.webSearch)
【讨论】:
很好的答案。对于记录在here 中的不同用例,还有其他很好的选择,例如。.keyboardType(.twitter)
和 .keyboardType(.phonePad)
【参考方案5】:
iOS 15.0+
macOS 12.0+, Mac 催化剂 15.0+, tvOS 15.0+, watchOS 8.0+
submitLabel(_:)
为此视图设置提交标签。
https://developer.apple.com
Form
TextField("Username", $viewModel.username)
.submitLabel(.done)
【讨论】:
以上是关于是否可以使用 SwiftUI 将键盘上的“返回”键更改为“完成”?的主要内容,如果未能解决你的问题,请参考以下文章