iOS键盘解雇与多个UIGestureRecognizers

时间:2017-01-30 15:49:32

标签: ios swift user-interface

在包含UITableViewUITapGestureRecognizer的主应用视图中,如果在外部检测到点按,则我使用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具有交互式标题单元格,每个 都附加了UITableView

最终结果是,如果我点击标题单元格,那个单元格上的手势识别器会被触发,而不是父视图上的手势识别器,并且键盘不会被解除。如果我点击数据单元格,一切正常。

如果重要,我的UIViewController有自己的UIView子类,并且包含在嵌套的Value中 - 该表太复杂了,无法在我的主视图控制器中使用该代码。 / p>

当附加父视图的识别器时,如何防止子视图的手势识别器处理这些点击,以便父视图可以处理它们?

1 个答案:

答案 0 :(得分:0)

通过观察UITableView's控制器中的虚拟键盘通知,跟踪键盘可见性状态,然后在标题上实现此UIGestureRecognizerDelegate方法,我实现了我认为的“临时”解决方案细胞的手势识别器:

func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    return !keyboardShowing
}

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

编辑 - 感谢@Tommy的提示,我现在有了一个更好的解决方案,无需在子视图中跟踪键盘状态。

我的父视图不再使用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()
    }
}