使用 UIViewRepresentable 在 SwiftUI 中自定义 TextField 键盘
Custom TextField keyboard in SwiftUI with UIViewRepresentable
我在 UIViewRepresentable 中使用自定义 UITextField,以获得仅带有小数位和自定义键盘工具栏的文本字段。目标是向工具栏添加基本内容,例如插入减号、E 等……我见过很多代码只处理“完成”按钮。我尝试将 insertText() 添加到按钮操作中,但我认为协调器未被调用,因此文本未更新。我想要的只是在光标位置插入自定义字符串的能力。
代码如下:
struct DataTextField: UIViewRepresentable {
private var placeholder: String
@Binding var text: String
init(_ placeholder: String, text: Binding<String>) {
self.placeholder = placeholder
self._text = text
}
func makeUIView(context: Context) -> UITextField {
let textfield = UITextField()
textfield.keyboardType = .decimalPad
textfield.delegate = context.coordinator
textfield.placeholder = placeholder
let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: textfield.frame.size.width, height: 44))
let minusButton = UIBarButtonItem(title: "-", style: .plain, target: self, action: #selector(textfield.minusButtonTapped(button:)))
let scientificButton = UIBarButtonItem(title: "E", style: .plain, target: self, action: #selector(textfield.scientificButtonTapped(button:)))
toolBar.items = [minusButton, scientificButton]
toolBar.setItems([minusButton, scientificButton], animated: true)
textfield.inputAccessoryView = toolBar
textfield.borderStyle = .roundedRect
textfield.textAlignment = .right
textfield.adjustsFontSizeToFitWidth = true
return textfield
}
func updateUIView(_ uiView: UITextField, context: Context) {
uiView.text = text
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UITextFieldDelegate {
var parent: DataTextField
init(_ textField: DataTextField) {
self.parent = textField
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let currentValue = textField.text as NSString? {
let proposedValue = currentValue.replacingCharacters(in: range, with: string) as String
self.parent.text = proposedValue
}
return true
}
}
}
extension UITextField {
@objc func minusButtonTapped(button:UIBarButtonItem) -> Void {
insertText("-")
}
@objc func scientificButtonTapped(button:UIBarButtonItem) -> Void {
insertText("E")
}
}
问题视频:
我发现这是一个 Swift 错误,它只会更新不在数组中的文本。 (在我的例子中,它是)经过几个小时的尝试,我发现调用 delegate?.textFieldDidBeginEditing?(self)
然后更新该函数内的文本可以使按钮按预期工作。
extension UITextField {
@objc func minusButtonTapped(button: UIBarButtonItem) -> Void {
insertText("-")
delegate?.textFieldDidBeginEditing?(self)
}
@objc func scientificButtonTapped(button: UIBarButtonItem) -> Void {
insertText("E")
delegate?.textFieldDidBeginEditing?(self)
}
}
将此添加到 UIViewRepresentable 中的协调器 class:
func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) {
textField.resignFirstResponder()
}
func textFieldDidBeginEditing(_ textField: UITextField) {
self.parent.text = textField.text!
}
必须调用 .resignFirstResponder()
。如果不关闭键盘,应用程序将崩溃,因为在我的例子中,视图本身可以关闭。
我在 UIViewRepresentable 中使用自定义 UITextField,以获得仅带有小数位和自定义键盘工具栏的文本字段。目标是向工具栏添加基本内容,例如插入减号、E 等……我见过很多代码只处理“完成”按钮。我尝试将 insertText() 添加到按钮操作中,但我认为协调器未被调用,因此文本未更新。我想要的只是在光标位置插入自定义字符串的能力。
代码如下:
struct DataTextField: UIViewRepresentable {
private var placeholder: String
@Binding var text: String
init(_ placeholder: String, text: Binding<String>) {
self.placeholder = placeholder
self._text = text
}
func makeUIView(context: Context) -> UITextField {
let textfield = UITextField()
textfield.keyboardType = .decimalPad
textfield.delegate = context.coordinator
textfield.placeholder = placeholder
let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: textfield.frame.size.width, height: 44))
let minusButton = UIBarButtonItem(title: "-", style: .plain, target: self, action: #selector(textfield.minusButtonTapped(button:)))
let scientificButton = UIBarButtonItem(title: "E", style: .plain, target: self, action: #selector(textfield.scientificButtonTapped(button:)))
toolBar.items = [minusButton, scientificButton]
toolBar.setItems([minusButton, scientificButton], animated: true)
textfield.inputAccessoryView = toolBar
textfield.borderStyle = .roundedRect
textfield.textAlignment = .right
textfield.adjustsFontSizeToFitWidth = true
return textfield
}
func updateUIView(_ uiView: UITextField, context: Context) {
uiView.text = text
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UITextFieldDelegate {
var parent: DataTextField
init(_ textField: DataTextField) {
self.parent = textField
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if let currentValue = textField.text as NSString? {
let proposedValue = currentValue.replacingCharacters(in: range, with: string) as String
self.parent.text = proposedValue
}
return true
}
}
}
extension UITextField {
@objc func minusButtonTapped(button:UIBarButtonItem) -> Void {
insertText("-")
}
@objc func scientificButtonTapped(button:UIBarButtonItem) -> Void {
insertText("E")
}
}
问题视频:
我发现这是一个 Swift 错误,它只会更新不在数组中的文本。 (在我的例子中,它是)经过几个小时的尝试,我发现调用 delegate?.textFieldDidBeginEditing?(self)
然后更新该函数内的文本可以使按钮按预期工作。
extension UITextField {
@objc func minusButtonTapped(button: UIBarButtonItem) -> Void {
insertText("-")
delegate?.textFieldDidBeginEditing?(self)
}
@objc func scientificButtonTapped(button: UIBarButtonItem) -> Void {
insertText("E")
delegate?.textFieldDidBeginEditing?(self)
}
}
将此添加到 UIViewRepresentable 中的协调器 class:
func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) {
textField.resignFirstResponder()
}
func textFieldDidBeginEditing(_ textField: UITextField) {
self.parent.text = textField.text!
}
必须调用 .resignFirstResponder()
。如果不关闭键盘,应用程序将崩溃,因为在我的例子中,视图本身可以关闭。