用户在SwiftUI中单击键盘上的删除按钮时的操作

时间:2019-11-08 17:28:57

标签: keyboard action swiftui

当用户尝试修改文本字段时,单击键盘上的删除按钮时,我会尝试运行一个功能。

我该怎么做?

enter image description here

1 个答案:

答案 0 :(得分:1)

是可以的,但是它需要继承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实现,因此我们需要三个可用于回调的函数。

  1. textFieldChangeHandler将在文本属性更新时被调用,并允许我们更改与Textfield相关的状态值。
  2. onCommitHandler,当我们完成对TextField的编辑后,将调用此名称
  3. deleteHandler,当我们执行他的删除操作时,将调用它。

上面的代码显示了如何使用它们。您最感兴趣的部分是override func deleteBackward(),通过覆盖此部分,我们可以在按下删除按钮并对其执行操作时挂入。根据使用情况,您可能希望在调用deleteHandler之前先调用super

下一步,我们需要创建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")
        })
    }
}