防止触摸从 UIControl 传递到 ParentView

Posted

技术标签:

【中文标题】防止触摸从 UIControl 传递到 ParentView【英文标题】:Preventing touch passing from UIControl to ParentView 【发布时间】:2018-09-27 15:33:24 【问题描述】:

我为 Uber 创建了一个自定义控件,例如 OTP TextField。我想在我的控件中使用触摸,而不是让它通过 UIResponder 链传播。所以我已经覆盖了apple documentation.中描述的方法

extension BVAPasswordTextField 
override func touchesBegan(_ touches: Set<UITouch>,  with event: UIEvent?) 
   becomeFirstResponder()
  

  override func touchesMoved(Set<UITouch>, with: UIEvent?) 



override func touchesEnded(Set<UITouch>, with: UIEvent?) 



override func touchesCancelled(Set<UITouch>, with: UIEvent?) 

 

override func touchesEstimatedPropertiesUpdated(Set<UITouch>) 

  

现在在某些视图控制器中,当用户点击自定义控件之外的任何位置时,我想关闭键盘。

override func viewDidLoad() 
    super.viewDidLoad()
    let tapGestureRecogniser = UITapGestureRecognizer(target: self, action: #selector(ViewController.backgroundTapped))
    tapGestureRecogniser.numberOfTapsRequired = 1
    view.addGestureRecognizer(tapGestureRecogniser)
    // Do any additional setup after loading the view, typically from a nib.


@objc func backgroundTapped() 
    self.view.endEditing(true)

但每当我点击文本字段时,backgroundTapped 也会被调用。

注意:- 这是一个控件,您可以根据枚举值创建不同的 UI 组件来获取输入。所以这个控件可以在整个团队之间共享......我不会是唯一使用它的人......所以我希望它的行为与触摸场景中的 UITextfield 完全一样

【问题讨论】:

【参考方案1】:

您可以使用UITapGestureRecognizerDelegate 处理点击手势。它允许您决定是否应该开始手势。在您的情况下,应该根据触摸的位置来完成。

extension ViewController: UIGestureRecognizerDelegate 
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool 
        let location = gestureRecognizer.location(in: self.view)
        // return true is location of touch is outside our textField
        return !textField.frame.contains(location)
    

只需确保您在viewDidLoad 处为您的手势设置了delegate

tapGestureRecogniser.delegate = self

更新

如果我的设置正确,您就有一个视图和一些用于输入的子视图。当这个super-view被触摸时,你想resignFirstResponder。在这种情况下,您可以像这样使用gestureRecognizerShouldBegin

func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool 
    let location = gestureRecognizer.location(in: self.view)
    for subview in self.view.subviews 
        if subview.frame.contains(location) 
            return false
        
    
    return true

在我看来,如果你想以特定的方式处理一些 view 交互,你需要使用特定的 view 来完成。而你现在所做的感觉就像是尝试使用 另一个 视图来改变一个 view 的行为。

【讨论】:

我知道...但它是一个控件,您可以根据枚举值创建不同的 UI 组件来获取输入。所以这个控件可以在整个团队之间共享......我不会是唯一使用它的人......所以我希望它的行为与触摸场景中的 UITextfield 完全一样...... @KeshavRaj 我已经更新了我的答案。可能我没有解决你的问题。但我试图解释我的观点。 我希望这个控件可以在任何视图控制器中使用,而不需要对 gestureRecognizerShouldBegin 进行任何特定编码.....如果我采用委托方法,那么无论我在哪里使用它,这个控件的所有者都需要实现这个委托方法...... UITextField 不是这种情况......所以我搜索了AppleDocumentation并找到了上面的链接(指定有问题)以防止触摸事件在UIResponder链层次结构中向上传播......但这不起作用.....希望我现在足够清楚 那你为什么不在你的控制视图上添加一个gestureRecognizer呢? github.com/keshavRaj/BVAotpTextField 通过提供图像或提供边框类型值并使用其他属性来查看我想要实现的目标.....所以它可以被多人使用......跨度>

以上是关于防止触摸从 UIControl 传递到 ParentView的主要内容,如果未能解决你的问题,请参考以下文章

如何忽略触摸事件并将它们传递给另一个子视图的 UIControl 对象?

UIControl 如何将所有触摸事件传递给响应者链中的下一个对象?

将触摸结束事件发送到 UIControl 子类

UIControl 跟踪在不同 UIControl 上开始的触摸

被覆盖的 UIControl 或 UIView 如何知道在其上方结束的触摸事件?

如何取消对子 UIControl 的触摸?