用户在 SwiftUI 中单击键盘上的删除按钮时的操作
Action when user click on the delete button on the keyboard in SwiftUI
我尝试 运行 当用户在尝试修改文本字段时单击键盘上的删除按钮时的功能。
我该怎么做?
是的,这是可能的,但是它需要子类化 UITextField
并创建您自己的 UIViewRepresentable
这个答案是基于 Costantino Pistagna 在他 medium article 中所做的出色工作,但我们需要做更多的工作。
首先我们需要创建UITextField
的子类,这也应该符合UITextFieldDelegate
协议。
class WrappableTextField: UITextField, UITextFieldDelegate {
var textFieldChangedHandler: ((String)->Void)?
var onCommitHandler: (()->Void)?
var deleteHandler: (() -> Void)?
override func deleteBackward() {
super.deleteBackward()
deleteHandler?()
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if let nextField = textField.superview?.superview?.viewWithTag(textField.tag + 1) as? UITextField {
nextField.becomeFirstResponder()
} else {
textField.resignFirstResponder()
}
return false
}
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)
textFieldChangedHandler?(proposedValue as String)
}
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
onCommitHandler?()
}
}
因为我们正在创建自己的 TextField
实现,所以我们需要三个可用于回调的函数。
textFieldChangeHandler
这将在文本 属性 更新时调用,并允许我们更改与我们的 Textfield
. 关联的状态值
onCommitHandler
这将在我们完成 TextField
编辑后调用
deleteHandler
当我们执行删除操作时会调用它。
上面的代码显示了这些是如何使用的。您特别感兴趣的部分是 override func deleteBackward()
,通过覆盖它,我们可以在按下删除按钮时挂钩并对其执行操作。根据您的用例,您可能希望在调用 super
.
之前调用 deleteHandler
接下来我们需要创建 UIViewRepresentable
.
struct MyTextField: UIViewRepresentable {
private let tmpView = WrappableTextField()
//var exposed to SwiftUI object init
var tag:Int = 0
var placeholder:String?
var changeHandler:((String)->Void)?
var onCommitHandler:(()->Void)?
var deleteHandler: (()->Void)?
func makeUIView(context: UIViewRepresentableContext<MyTextField>) -> WrappableTextField {
tmpView.tag = tag
tmpView.delegate = tmpView
tmpView.placeholder = placeholder
tmpView.onCommitHandler = onCommitHandler
tmpView.textFieldChangedHandler = changeHandler
tmpView.deleteHandler = deleteHandler
return tmpView
}
func updateUIView(_ uiView: WrappableTextField, context: UIViewRepresentableContext<MyTextField>) {
uiView.setContentHuggingPriority(.defaultHigh, for: .vertical)
uiView.setContentHuggingPriority(.defaultLow, for: .horizontal)
}
}
这是我们创建 WrappableTextField
的 SwiftUI 版本的地方。我们创建 WrappableTextField
及其属性。在 makeUIView
函数中,我们分配这些属性。最后在 updateUIView
中,我们设置了内容拥抱属性,但您可以选择不这样做,这实际上取决于您的用例。
最后我们可以创建一个小的工作示例。
struct ContentView: View {
@State var text = ""
var body: some View {
MyTextField(tag: 0, placeholder: "Enter your name here", changeHandler: { text in
// update the state's value of text
self.text = text
}, onCommitHandler: {
// do something when the editing finishes
print("Editing ended")
}, deleteHandler: {
// do something here when you press delete
print("Delete pressed")
})
}
}
我尝试 运行 当用户在尝试修改文本字段时单击键盘上的删除按钮时的功能。
我该怎么做?
是的,这是可能的,但是它需要子类化 UITextField
并创建您自己的 UIViewRepresentable
这个答案是基于 Costantino Pistagna 在他 medium article 中所做的出色工作,但我们需要做更多的工作。
首先我们需要创建UITextField
的子类,这也应该符合UITextFieldDelegate
协议。
class WrappableTextField: UITextField, UITextFieldDelegate {
var textFieldChangedHandler: ((String)->Void)?
var onCommitHandler: (()->Void)?
var deleteHandler: (() -> Void)?
override func deleteBackward() {
super.deleteBackward()
deleteHandler?()
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if let nextField = textField.superview?.superview?.viewWithTag(textField.tag + 1) as? UITextField {
nextField.becomeFirstResponder()
} else {
textField.resignFirstResponder()
}
return false
}
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)
textFieldChangedHandler?(proposedValue as String)
}
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
onCommitHandler?()
}
}
因为我们正在创建自己的 TextField
实现,所以我们需要三个可用于回调的函数。
textFieldChangeHandler
这将在文本 属性 更新时调用,并允许我们更改与我们的Textfield
. 关联的状态值
onCommitHandler
这将在我们完成TextField
编辑后调用
deleteHandler
当我们执行删除操作时会调用它。
上面的代码显示了这些是如何使用的。您特别感兴趣的部分是 override func deleteBackward()
,通过覆盖它,我们可以在按下删除按钮时挂钩并对其执行操作。根据您的用例,您可能希望在调用 super
.
deleteHandler
接下来我们需要创建 UIViewRepresentable
.
struct MyTextField: UIViewRepresentable {
private let tmpView = WrappableTextField()
//var exposed to SwiftUI object init
var tag:Int = 0
var placeholder:String?
var changeHandler:((String)->Void)?
var onCommitHandler:(()->Void)?
var deleteHandler: (()->Void)?
func makeUIView(context: UIViewRepresentableContext<MyTextField>) -> WrappableTextField {
tmpView.tag = tag
tmpView.delegate = tmpView
tmpView.placeholder = placeholder
tmpView.onCommitHandler = onCommitHandler
tmpView.textFieldChangedHandler = changeHandler
tmpView.deleteHandler = deleteHandler
return tmpView
}
func updateUIView(_ uiView: WrappableTextField, context: UIViewRepresentableContext<MyTextField>) {
uiView.setContentHuggingPriority(.defaultHigh, for: .vertical)
uiView.setContentHuggingPriority(.defaultLow, for: .horizontal)
}
}
这是我们创建 WrappableTextField
的 SwiftUI 版本的地方。我们创建 WrappableTextField
及其属性。在 makeUIView
函数中,我们分配这些属性。最后在 updateUIView
中,我们设置了内容拥抱属性,但您可以选择不这样做,这实际上取决于您的用例。
最后我们可以创建一个小的工作示例。
struct ContentView: View {
@State var text = ""
var body: some View {
MyTextField(tag: 0, placeholder: "Enter your name here", changeHandler: { text in
// update the state's value of text
self.text = text
}, onCommitHandler: {
// do something when the editing finishes
print("Editing ended")
}, deleteHandler: {
// do something here when you press delete
print("Delete pressed")
})
}
}