菜鸟教程小白 发表于 2022-12-11 18:46:30

使用多个 UIGestureRecognizers 解除 iOS 键盘


                                            <p><p>在包含 <code>UITextField</code> 和 <code>UITableView</code> 的主应用程序 View 中,我有使用 <code>UITapGestureRecognizer</code> 来关闭的“常规”代码如果在我编辑 <code>UITextField</code> 的内容时在键盘外检测到点击,则虚拟键盘。</p>

<p>一个附加功能是,只有在实际显示虚拟键盘时才启用此功能 - 如果虚拟键盘不可见,我不希望“背景点击”导致编辑结束,但我也不希望背景点击触发它们的正常行为 - 如果虚拟键盘当前正在显示,它们应该被消耗掉。</p>

<pre><code>override func viewDidLoad() {
    ...

    tapper = UITapGestureRecognizer(target: self, action: #selector(viewTapped))

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardShown), name:
      NSNotification.Name(rawValue: &#34;UIKeyboardDidShowNotification&#34;), object: nil)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardHidden), name:
      NSNotification.Name(rawValue: &#34;UIKeyboardDidHideNotification&#34;), object: nil)
}

@IBAction func keyboardShown(_ sender: AnyObject) {
    view.addGestureRecognizer(tapper!)
}

@IBAction func keyboardHidden(_ sender: AnyObject) {
    view.removeGestureRecognizer(tapper!)
}

@IBAction func viewTapped(_ sender: AnyObject) {
    view.endEditing(false)
}
</code></pre>

<p>这个<em>大部分</em>可以工作,除了 <code>UITableView</code> 有交互式标题单元格,每个 <em>也</em> 有一个 <code>UITapGestureRecognizer</code> 附加.</p>

<p>最终结果是,如果我单击标题单元格,则该单元格上的手势识别器会被触发,而不是父 View 上的手势识别器,并且键盘不会被关闭。如果我点击数据单元格,一切正常。</p>

<p>如果重要的话,我的 <code>UITableView</code> 有自己的 <code>UIViewController</code> 子类,并且包含在嵌套的 <code>UIView</code> 中 - 表格太复杂了我的主视图 Controller 中的代码。</p>

<p>当附加了父 View 的识别器以便父 View 可以处理它们时,如何防止 subview 的手势识别器处理这些点击?</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>我通过观察 <code>UITableView 的</code>Controller 中的虚拟键盘通知,跟踪键盘可见性状态,然后实现这个 <code>UIGestureRecognizerDelegate</code> 标题单元格手势识别器上的方法:</p>

<pre><code>func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -&gt; Bool {
    return !keyboardShowing
}
</code></pre>

<p>这从 subview 中的主视图复制了一定数量的功能,实际上不需要知道键盘的状态。我仍在寻找一种可以完全在父 View 中处理的方法。</p>

<hr/>

<p><strong>编辑</strong> - 感谢@Tommy 的提示,我现在有了一个更好的解决方案,无需在 subview 中跟踪键盘状态。</p>

<p>我的父 View 不再使用 <code>UIGestureRecognizer</code>,而是使用 <code>UIView</code> 的自定义子类来跟踪触摸事件,并有条件地忽略它们:</p>

<pre><code>class KeyboardDismissingView: UIView {

    private var keyboardVisible = false

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -&gt; UIView? {
      guard let r = super.hitTest(point, with: event) else { return nil }
      var v : UIView! = r
      while v != nil {
            if v is UITextField {
                return r
            }
            v = v.superview
      }

      if keyboardVisible {
            self.endEditing(false)
            return nil
      }

      return r
    }

    func setup() {
      NotificationCenter.default.addObserver(self, selector: #selector(keyboardShown), name:
            NSNotification.Name(rawValue: &#34;UIKeyboardDidShowNotification&#34;), object: nil)

      NotificationCenter.default.addObserver(self, selector: #selector(keyboardHidden), name:
            NSNotification.Name(rawValue: &#34;UIKeyboardDidHideNotification&#34;), object: nil)
    }

    @IBAction func keyboardShown(_ sender: AnyObject) {
      keyboardVisible = true
    }

    @IBAction func keyboardHidden(_ sender: AnyObject) {
      keyboardVisible = false
    }

    override init (frame: CGRect) {
      super.init(frame: frame)
      setup()
    }

    required init(coder aDecoder: NSCoder) {
      super.init(coder: aDecoder)!
      setup()
    }
}
</code></pre></p>
                                   
                                                <p style="font-size: 20px;">关于使用多个 UIGestureRecognizers 解除 iOS 键盘,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/41940015/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/41940015/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: 使用多个 UIGestureRecognizers 解除 iOS 键盘