iOS:如何重写含UITextField的自定义UIView的编辑手势识别器?
解决自定义UIView内UITextField编辑事件的问题
嘿,我懂你现在的处境——当你把UITextField封装到自定义UIView里复用之后,再想修改它的编辑事件行为,确实不像直接用原生UITextField那么顺手。其实不用纠结“重写手势识别器”,这里有几个更直接靠谱的方案,能帮你搞定这个问题:
方法一:代理转发(最常用的标准方案)
我们可以给自定义视图创建专属的代理协议,把内部UITextField的编辑事件转发出去,这样外部使用这个自定义视图时,就能像处理原生UITextField一样响应事件:
// 定义自定义视图的代理协议 protocol CustomTextFieldViewDelegate: AnyObject { func customTextFieldViewDidBeginEditing(_ view: CustomTextFieldView) func customTextFieldViewDidEndEditing(_ view: CustomTextFieldView) } class CustomTextFieldView: UIView { // 内部封装的UITextField private let textField = UITextField() // 自定义代理对象 weak var delegate: CustomTextFieldViewDelegate? override init(frame: CGRect) { super.init(frame: frame) setupTextField() } required init?(coder: NSCoder) { super.init(coder: coder) setupTextField() } private func setupTextField() { // 配置textField的基础样式(按需调整) textField.borderStyle = .roundedRect // 设置textField的代理为当前自定义视图 textField.delegate = self // 添加到视图并设置布局约束 addSubview(textField) textField.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ textField.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8), textField.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8), textField.topAnchor.constraint(equalTo: topAnchor, constant: 4), textField.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -4) ]) } } // 实现UITextFieldDelegate,将事件转发给自定义代理 extension CustomTextFieldView: UITextFieldDelegate { func textFieldDidBeginEditing(_ textField: UITextField) { delegate?.customTextFieldViewDidBeginEditing(self) } func textFieldDidEndEditing(_ textField: UITextField) { delegate?.customTextFieldViewDidEndEditing(self) } }
外部使用时,只需要设置自定义视图的代理并实现协议方法即可:
class YourViewController: UIViewController, CustomTextFieldViewDelegate { override func viewDidLoad() { super.viewDidLoad() let customTextFieldView = CustomTextFieldView(frame: CGRect(x: 20, y: 100, width: 300, height: 44)) customTextFieldView.delegate = self view.addSubview(customTextFieldView) } // 实现自定义代理方法 func customTextFieldViewDidBeginEditing(_ view: CustomTextFieldView) { // 这里写你需要的开始编辑逻辑 print("自定义视图内的输入框开始编辑了") } func customTextFieldViewDidEndEditing(_ view: CustomTextFieldView) { // 这里写你需要的结束编辑逻辑 print("自定义视图内的输入框结束编辑了") } }
方法二:闭包回调(更简洁的轻量方案)
如果觉得代理模式太繁琐,也可以给自定义视图添加闭包属性,直接把编辑事件通过闭包传递出去,代码更简洁:
class CustomTextFieldView: UIView { private let textField = UITextField() // 定义编辑事件的闭包属性 var didBeginEditing: (() -> Void)? var didEndEditing: (() -> Void)? override init(frame: CGRect) { super.init(frame: frame) setupTextField() } required init?(coder: NSCoder) { super.init(coder: coder) setupTextField() } private func setupTextField() { textField.borderStyle = .roundedRect textField.delegate = self addSubview(textField) // 布局约束同上... } } extension CustomTextFieldView: UITextFieldDelegate { func textFieldDidBeginEditing(_ textField: UITextField) { // 触发开始编辑的闭包 didBeginEditing?() } func textFieldDidEndEditing(_ textField: UITextField) { // 触发结束编辑的闭包 didEndEditing?() } }
外部使用时直接赋值闭包即可:
let customTextFieldView = CustomTextFieldView(frame: CGRect(x: 20, y: 100, width: 300, height: 44)) customTextFieldView.didBeginEditing = { print("输入框开始编辑啦") } customTextFieldView.didEndEditing = { print("输入框结束编辑啦") } view.addSubview(customTextFieldView)
方法三:修改手势识别器(仅当需要改变触发逻辑时使用)
如果你确实需要修改UITextField的手势(比如替换默认的点击手势为双击、长按等),可以在自定义视图中找到并修改它的手势识别器:
private func setupTextField() { // 移除默认的点击手势(如果需要替换的话) if let defaultTap = textField.gestureRecognizers?.first(where: { $0 is UITapGestureRecognizer }) { textField.removeGestureRecognizer(defaultTap) } // 添加自定义的双击手势 let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap)) doubleTapGesture.numberOfTapsRequired = 2 textField.addGestureRecognizer(doubleTapGesture) // 确保textField允许用户交互 textField.isUserInteractionEnabled = true } @objc private func handleDoubleTap() { // 手动触发开始编辑 textField.becomeFirstResponder() // 执行自定义逻辑 print("双击触发了输入框编辑") }
小提醒
其实UITextField的EditingDidBegin/EditingDidEnd本质是通过UITextFieldDelegate传递的事件,不是直接由手势触发的——所以如果只是要修改这两个事件的行为,代理或闭包的方案会更简单,不需要动手势识别器。只有当你需要改变“触发编辑的手势条件”时,才需要修改手势。
内容的提问来源于stack exchange,提问作者Rashad Akoodie
相关产品推荐
相关产品推荐

