在包含 UITextField 和 UITableView 的主应用程序 View 中,我有使用 UITapGestureRecognizer 来关闭的“常规”代码如果在我编辑 UITextField 的内容时在键盘外检测到点击,则虚拟键盘。
一个附加功能是,只有在实际显示虚拟键盘时才启用此功能 - 如果虚拟键盘不可见,我不希望“背景点击”导致编辑结束,但我也不希望背景点击触发它们的正常行为 - 如果虚拟键盘当前正在显示,它们应该被消耗掉。
override func viewDidLoad() {
...
tapper = UITapGestureRecognizer(target: self, action: #selector(viewTapped))
NotificationCenter.default.addObserver(self, selector: #selector(keyboardShown), name:
NSNotification.Name(rawValue: "UIKeyboardDidShowNotification"), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardHidden), name:
NSNotification.Name(rawValue: "UIKeyboardDidHideNotification"), 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)
}
这个大部分可以工作,除了 UITableView 有交互式标题单元格,每个 也 有一个 UITapGestureRecognizer 附加.
最终结果是,如果我单击标题单元格,则该单元格上的手势识别器会被触发,而不是父 View 上的手势识别器,并且键盘不会被关闭。如果我点击数据单元格,一切正常。
如果重要的话,我的 UITableView 有自己的 UIViewController 子类,并且包含在嵌套的 UIView 中 - 表格太复杂了我的主视图 Controller 中的代码。
当附加了父 View 的识别器以便父 View 可以处理它们时,如何防止 subview 的手势识别器处理这些点击?
Best Answer-推荐答案 strong>
我通过观察 UITableView 的 Controller 中的虚拟键盘通知,跟踪键盘可见性状态,然后实现这个 UIGestureRecognizerDelegate 标题单元格手势识别器上的方法:
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return !keyboardShowing
}
这从 subview 中的主视图复制了一定数量的功能,实际上不需要知道键盘的状态。我仍在寻找一种可以完全在父 View 中处理的方法。
编辑 - 感谢@Tommy 的提示,我现在有了一个更好的解决方案,无需在 subview 中跟踪键盘状态。
我的父 View 不再使用 UIGestureRecognizer ,而是使用 UIView 的自定义子类来跟踪触摸事件,并有条件地忽略它们:
class KeyboardDismissingView: UIView {
private var keyboardVisible = false
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> 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: "UIKeyboardDidShowNotification"), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardHidden), name:
NSNotification.Name(rawValue: "UIKeyboardDidHideNotification"), 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()
}
}
关于使用多个 UIGestureRecognizers 解除 iOS 键盘,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/41940015/
|