0
  1. I have a message chat box similar to most chat apps. The box goes up when when you start editing the messagetextView.

  2. As is standard, there is a tap gesture recognizer that is called when the user taps anywhere else, which dismisses the keyboard.

  3. I have another button that is visible next to the chat box.

  4. Currently when the user taps the button, instead of triggering that ibaction, it dismisses the keyboard. Then when they tap on it again the ibaction is called. So the user has to tap twice to trigger the button when the keyboard is up.

Is there a way configure the button or gesture recognizer so that they both get called when the user taps in that location?

  • alternatively, is there a better design solution to solve something like this?
  • note: I read that in this situation ios will either choose the responder tree or gesture recognizer tree. So perhaps traversing both. How?

1 Answers1

0

There are several ways to solve this problem.

It seems like the view your add tap gesture is above the button.

Set tapGesture's delegate and implement the UIGestureRecognizerDelegate.

Disable the tap gesture when tap the button.

class MessageViewController: UIViewController {
    
    private lazy var button = UIButton(type: .custom)
    
    weak var tapGesture: UITapGestureRecognizer?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let tap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard(_:)))
        tap.delegate = self
        view.addGestureRecognizer(tap)
    }
    
    
    @objc private func dismissKeyboard(_ sender: Any?) {
        // dismiss the keyboard
    }
    
    @objc private func nextButtonOnClicked(_ sender: Any?) {
        // dismiss the keyboard if need
        // go next
    }
}

extension MessageViewController: UIGestureRecognizerDelegate {
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        guard let tapGesture = tapGesture,
              gestureRecognizer == tapGesture
        else { return true }
        
        if button.frame.contains(tapGesture.location(in: view)) {
            return false
        } else {
            return true
        }
    }
}

Or just set the tapGesture's view below the button.

Dark Zhao
  • 22
  • 4