0
votes

I'm using this code to hide the keyboard when the user taps anywhere on the screen outside of the TextView:

 override func viewDidLoad() {
        super.viewDidLoad()
        //Looks for single or multiple taps.
        let tap = UITapGestureRecognizer(target: self, action: #selector(UIInputViewController.dismissKeyboard))
        tap.delegate = self
        //Uncomment the line below if you want the tap not not interfere and cancel other interactions.
        tap.cancelsTouchesInView = false
        view.addGestureRecognizer(tap)
    }
    
    //Calls this function when the tap is recognized.
    @objc func dismissKeyboard() {
        //Causes the view (or one of its embedded text fields) to resign the first responder status.
        view.endEditing(true)
    }
    
    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        if touch.view is UIButton {
            return false
        }
        return true
    }

The problem is I have a UIButton in this view as well - when I tap on the button, the button's gesture recognizer function is not called. Instead, dismissKeyboard is called. I already tried the suggestion of using tap.cancelsTouchesInView = false as well as the shouldReceive method, but neither of them work - in the shouldReceive method, when I tap on the button, the class of touch.view is UIView.

Does anybody know how to allow the user to hide the keyboard when clicking anywhere on screen, but also allow button action handlers to execute?

2

2 Answers

0
votes

I fixed this using the following code:

  1. I detect the location of the user's touch

  2. I check if the touch is in the frame of each of the two buttons in my UIView

  3. If this is true, I manually call the button handler and return false from the method

    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
     if let view = self.view as? MyViewControllersView {
         let location = touch.location(in: self.view)
         if view.saveButton.frame.contains(location) {
             view.saveHit()
             return false
         } else if view.scanButton.frame.contains(location) {
             view.scanHit()
             return false
         }
     }
     return true
    }
    
0
votes

it works for me, please check out

//MARK:- View Lyfe cycle
override func viewDidLoad() {
    super.viewDidLoad()
     IQKeyboardManager.shared().isEnableAutoToolbar = false
//        IQKeyboardManager.shared().disabledToolbarClasses = self
    IQKeyboardManager.shared().isEnabled = false
    self.keyboardWillShowAndHide()
    initializeHideKeyboard()
 }

//MARK:- KayBoard Handling...
//MARK:- Init Hide KeyBoard...
func initializeHideKeyboard(){
    //Declare a Tap Gesture Recognizer which will trigger our dismissMyKeyboard() function
    let tap: UITapGestureRecognizer = UITapGestureRecognizer(
        target: self,
        action: #selector(dismissMyKeyboard))
    //Add this tap gesture recognizer to the parent view
    view.addGestureRecognizer(tap)
}
//MARK:- Dismissing Keyboard...
@objc func dismissMyKeyboard(){
    //endEditing causes the view (or one of its embedded text fields) to resign the first responder status.
    //In short- Dismiss the active keyboard.
    view.endEditing(true)
}
//MARK:- Kayboard Hide and Show...
func keyboardWillShowAndHide(){
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(keyboardWillShow),
        name: UIResponder.keyboardWillShowNotification,
        object: nil
    )
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(keyboarddidHide),
        name: UIResponder.keyboardWillHideNotification,
        object: nil
    )
    
}
//MARK:- KeyBoard Will Show
@objc func keyboardWillShow(_ notification: Notification) {
    self.arrConversationList.count
    if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
        let keyboardRectangle = keyboardFrame.cgRectValue
        let keyboardHeight = keyboardRectangle.height
        self.ChatBottomConstraint.constant = keyboardHeight - self.bottomLayoutGuide.length
        DispatchQueue.main.asyncAfter(deadline: .now()+0.1, execute: {
            if  self.arrConversationList.count > 0 {
                let indexPath = NSIndexPath(row: self.arrConversationList.count-1, section: 0)
                self.ConversationTblref.scrollToRow(at: indexPath as IndexPath, at: .bottom, animated: true)
            }
        })
        self.tableviewbottomconstraintref.constant = 0
        ConversationTblref.reloadData()
    }
}
//MARK:- KeyBoard Will Hide
@objc func keyboarddidHide(_ notification: Notification) {
    self.tableviewbottomconstraintref.constant = 0
    self.ChatBottomConstraint.constant = 0
    ConversationTblref.reloadData()
}

//MARK:- View Disappear for handleing kayboard...
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(true)
    IQKeyboardManager.shared().isEnableAutoToolbar = true
    IQKeyboardManager.shared().isEnabled = true
     NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
    

}

override func viewDidDisappear(_ animated: Bool) {
   
}