UITextView 的 UIGestureRecognizer 防止键盘在点击时出现

Posted

技术标签:

【中文标题】UITextView 的 UIGestureRecognizer 防止键盘在点击时出现【英文标题】:UITextView's UIGestureRecognizer preventing keyboard from appearing on tap 【发布时间】:2019-06-13 14:55:31 【问题描述】:

我有一个 UITextView,我在其上附加了一个手势识别器,如下所示:

let testTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(textTextViewTapped(gestureRecognizer:)))
testTapGestureRecognizer.cancelsTouchesInView = false
testTapGestureRecognizer.delaysTouchesBegan = false
testTapGestureRecognizer.delaysTouchesEnded = false
if textTextView != nil 
    textTextView!.addGestureRecognizer(testTapGestureRecognizer)

上面提到的选择器如下:

@objc func textTextViewTapped(gestureRecognizer: UIGestureRecognizer) 
    print("testTextViewTapped called.")

每次我点击 UITextView 时,我都可以在控制台上看到上面打印的消息。但是,键盘不再出现。

我发现 Apple 的文档在这里令人困惑: Here,上面写着

手势识别器不参与视图的响应器 链。

我将其解释为任何手势也会被发送到视图并向上发送,这是正常的。

稍后在同一页上,它说,

如果手势识别器识别出它的手势,剩余的触摸 因为视图被取消了。

这意味着如果一个附加的手势识别器能够将一个手势理解为它应该识别的那个,那么它将阻止它被传递到它所附加的视图。此外,它指定了 3 个应该能够阻止手势识别器这样做的属性。如上所示,我已在我的代码中将它们都设置为 false。

这里实际发生了什么,如何让 UITextView 正常解释触摸并能够使用手势识别器?

【问题讨论】:

为什么需要在文本视图中添加手势识别器?你想做什么? 完全不相关,但像 if x != nil x!... 这样的代码在 Swift 中是一个糟糕的模式。你应该这样做:if let x = x x... . @rmaddy 我正在尝试清除一些占位符文本,然后用户才能开始输入。另外,同意模式不好。还在学习。感谢您的提示。 您是否尝试在UITextView 中复制UITextField 的占位符行为? 查看*** answer 【参考方案1】:

您可以使用UIGestureRecognizerDelegate 使UITapGestureRecognizer 与常规UITextView 行为一起工作:

class TestViewController: UIViewController 

    @IBOutlet weak var textView: UITextView!

    override func viewDidLoad() 
        super.viewDidLoad()

        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(tap))
        tapGestureRecognizer.delegate = self

        textView.addGestureRecognizer(tapGestureRecognizer)
    

    @objc private func tap() 
        print("tap")
    



extension TestViewController: UIGestureRecognizerDelegate 

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool 
        return true
    


【讨论】:

【参考方案2】:

当用户点击它时,UITextView 可能有它自己的私有手势识别器来处理。发生这种情况时,它会使文本视图成为第一响应者,从而导致键盘出现。手势识别器可以强制其他手势识别器在识别他们的手势时失败。 (参见docs)也许这就是您添加轻击手势时发生的情况。它会识别点击并因此强制其他手势失败,从而阻止文本视图成为第一响应者。

最好的解决方案是遵循 question 的答案(正如 @FrancescoDeliro 在 cmets 中提到的那样)并使用委托调用来了解编辑何时开始/结束。

【讨论】:

感谢您的解释。这说得通。但是,在我看来,拥有一个未公开且被开发人员定义的显式手势识别器静默阻止的手势识别器似乎是一个糟糕的设计。

以上是关于UITextView 的 UIGestureRecognizer 防止键盘在点击时出现的主要内容,如果未能解决你的问题,请参考以下文章

当 UITextView 的文本超出 1 行时展开 UITextView 和 UITableView

选择另一个 UITextView 时,如何阻止 UITextView 退出第一响应者/关闭键盘?

UITextView 数据变化迅速

UITextView contentInset 在 iOS 7 上的 UITextView 中不起作用?

光标未显示在 UITextView

UITextView 设置属性后做啥?