简体   繁体   中英

Detect tap on UIView's "empty space"

I've got a view hierarchy that looks like that

UIScrollView
 |
 +- UIView
     |
     +- UITextField
     +- UITextField
     +- UIButton

What I want is for user which tapped one of the text fields and sees the keyboard on the screen to be able to tap on an "empty space" of UIView to hide keyboard. So, I don't want, for instance, an event from UIButton to bubble up to UIView (that's exactly what happens if I add UITapGestureRecognizer to UIView).

How can I achieve the desired functionality?

In your viewDidLoad method add this gesture recognizer:

UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
gestureRecognizer.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:gestureRecognizer];

Then add the dismissKeyboard method:

- (void) dismissKeyboard{
   [YOURFIELDHERE resignFirstResponder];
} 

You also need to add this to make it so the buttons are still clickable and not overridden by the gesture recognizer:

gestureRecognizer.delegate = self; // in viewDidLoad
<UIGestureRecognizerDelegate> //in your header file

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {

  if ([touch.view isKindOfClass:[UIButton class]]){
    return NO;
  }
  return YES; // handle the touch
}

I encounter this same problem and solve it with a naive solution.

  1. Change the View from an instance of UIView to an instance of UIControl so that it can handle touch events.
  2. Create an IBAction method in the View Controller that handles the touch event. In this case, we will resign any first responder from the view's subviews.

    - (IBAction)backgroundTapped:(id)sender { [contentView endEditing:YES]; }

    contentView is just the instance variable pointing to the View. You can name it anything you want. When you passed the message endEditing to the View, it essentially tells its subviews to resign first responder, thus dismissing the keyboard.

  3. Connect the target (View) and action (IBAction method you just created) via Interface Builder, by opening the connection inspector of the View, select Touch Up Inside and drag it to the File's Owner object, then select the name of the method.

Hopefully it helps.

I know it's a little late, but a quick, simple solution is the following:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    [self.view endEditing:YES];
}

It gets called if you tap on any empty space.

Mike Z's answer is good. But I think the "if condition" below would be easier and simple in UIGestureRecognizerDelegate when you use Mike Z's answer .

Especially when the subviews are not only a button type, they may also be UITableViewCell, Custom View, etc.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    return touch.view == yourEmptySpaceView;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM