简体   繁体   中英

How do I determine when the background area is tapped?

I am trying to determine when a user taps on some area other than the single UITextView I have on the screen. This is similar to this question about UITableViews , but I have a few problems with the solutions presented there. When the keyboard is dismissed, I scroll the screen a bit to hide where the keyboard was. My problem is that when I use UITapGestureRecognizer to determine if the screen was tapped, the tap doesn't go through to the other controls on the screen. I am using gestureRecognizer.cancelsTouchesInView = NO, it's a problem with the timing. The screen scrolls away before the control recognizes that it was clicked. Any idea how I can solve the problem? I'm perfectly happy using something other than gesture recognition.

我曾经使用自定义(不可见)按钮作为背景图层来执行此操作。

Keep the gesture recognizer. Have it use a method like this:

- (void)dismissKeyboard:(UIGestureRecognizer *)gesture
{
    [self.view endEditing:NO];
}

I found the solution to the problem. I'm still using the UITapGestureRecognizer, but I now have a zero-length delay before hiding the keyboard, which allows the tap event to propagate correctly to the subviews, such as buttons. The basic view is a text field and button controls filling the screen. To allow the screen to be viewed correctly when the keyboard is shown, the whole thing is wrapped in a scroll view, and a placeholder view for the area the keyboard takes up is added to the bottom. It is only expanded when the keyboard is shown. Here are all the relevant pieces of code, which should allow anyone to implement the tap-anywhere-to-dismiss-keyboard idea as well as solving the problem of controls being hidden by the keyboard:

- (void)viewDidLoad {
    [super viewDidLoad];
    ...
    UITapGestureRecognizer *tapRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget: self action: @selector(hideKeyboardWithDelay)] autorelease];
    tapRecognizer.cancelsTouchesInView = NO;
    [self.view addGestureRecognizer: tapRecognizer];
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(keyboardWillBeShown:) name: UIKeyboardWillShowNotification object: nil];
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(keyboardWillBeHidden:) name: UIKeyboardWillHideNotification object: nil];
}

- (void) hideKeyboardWithDelay {
    // using afterDelay allows the event to go through to any button before scrolling
    [self performSelector: @selector(hideKeyboard) withObject: nil afterDelay: 0.0f];
}

- (void) hideKeyboard {
    [self.myTextField1 resignFirstResponder];
    [self.myTextField2 resignFirstResponder];
}


- (void) keyboardWillBeShown: (NSNotification *) notification {
    NSDictionary* info = [notification userInfo];
    CGSize keyboardSize = [[info objectForKey: UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGRect frame = self.keyboardPlaceholder.frame;
    self.keyboardPlaceholder.frame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, keyboardSize.height);
    CGFloat contentHeight = self.scrollView.contentSize.height + keyboardSize.height + 20; // in my case, save 20px for the status bar
    self.scrollView.contentSize = CGSizeMake(frame.size.width, contentHeight);
    [self.scrollView scrollRectToVisible: self.keyboardPlaceholder.frame animated: YES];
}

- (void) keyboardWillBeHidden: (NSNotification *) notification {
    CGRect frame = self.keyboardPlaceholder.frame;
    NSDictionary* info = [notification userInfo];
    NSValue* value = [info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
    NSTimeInterval duration = 0.3f; // default keyboard animation time
    [value getValue: &duration];

    [UIView beginAnimations: @"hideKeyboardAnimation" context: nil];
    [UIView setAnimationDuration: duration];
    [UIView setAnimationCurve: UIViewAnimationCurveEaseInOut];

    self.keyboardPlaceholder.frame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, 0);   
    self.scrollView.contentSize = self.view.frame.size;

    [UIView commitAnimations]; 
}

- (void)viewDidUnload { 
    [[NSNotificationCenter defaultCenter] removeObserver: self];
    [super viewDidUnload];
}

Hope someone finds this useful.

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