Hide keyboard on touch anywhere outside UITextField when view includes UICollectionView

4.1k Views Asked by At

There are some answers out there such as this, but in the case where there is a UIScrollView or UICollectionView present, it doesn't work.
The touchesBegan method on the viewController will never get called.

On screen, I have a UITextField at the top.
Below that, filling up the rest of the screen is a UICollectionView.
I need to dismiss the keyboard if I touch anywhere besides the UITextField (including the collection view obviously)

So what is the best way to do this?

For such a common UI paradigm it seems like there should be a well-known solution, but I've yet to come across it.

3

There are 3 best solutions below

2
On

To dismiss Keyboard on tap of the View: Add a Tap gesture to your ViewController.collectionView as follows:

//declare a property to store your current responder
@property (nonatomic, assign) id currentResponder;
//in viewDidLoad:

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(resignOnTap:)];
    [singleTap setNumberOfTapsRequired:1];
    [singleTap setNumberOfTouchesRequired:1];
    [self.collectionView addGestureRecognizer:singleTap];


//Implement the below delegate method:

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    self.currentResponder = textField;
}

//Implement resignOnTap:

- (void)resignOnTap:(id)sender {
    [self.currentResponder resignFirstResponder];
}
0
On

Here's a better solution which doesn't require adding gesture recognisers individually to everything. It's in Swift, but could easily be converted to ObjC.

Add the following to your viewDidLoad():

let tap = UITapGestureRecognizer(target: self, action: "dismissKeyboard")
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)

and then add the following method declaration:

func dismissKeyboard()
{
    view.endEditing(true)
}

...where view is your text field.

0
On

The simple way to do it is:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [self.view endEditing:YES]; 
}