tags:

views:

875

answers:

5

I have a UITableView with UITextFields as cells. I would like to dismiss the keyboard when the background of the UITableView is touched. I'm trying to do this by creating a UIButton the size of the UITableView and placing it behind the UITableView. The only problem is the UIButton is catching all the touches even when the touch is on the UITableView. What am I doing wrong?

Thanks!

+2  A: 

I did it like this:

Create a method in your TableViewController to de-activate first responder (which would be your TextBox at that point)

- (BOOL)findAndResignFirstResonder: (UIView*) stView
{
    if (stView.isFirstResponder) {
        [stView resignFirstResponder];
        return YES;     
    }
    for (UIView *subView in stView.subviews) {
        if ([self findAndResignFirstResonder: subView])
            return YES;
    }
    return NO;
}

In didSelectRowAtIndexPath method call previous method:

- (void) tableView: (UITableView*) tableView didSelectRowAtIndexPath: (NSIndexPath*) indexPath {
...
    [self findAndResignFirstResonder: self.view];
...
}
sha
This will dismiss the keyboard but it isn't what I'm asking for...
Hua-Ying
you are doing it wrong the way you are asking. you don't put a button on the view you tell the view to remove the keyboard like this answer says
fuzzy lollipop
This works beautifully if you tap within a table view cell (and outside of any UITextField within that table view cell). However, if I tap the background of the table view (which is often an easier target to get at - yay Fitts's Law!), no such luck. True, that's expected, since we're performing this operation within tableView:didSelectRowAtIndexPath:. If this can be adjusted somehow to work with tapping anywhere else in the table view (that wouldn't otherwise want keyboard focus), I think we've got a winner here!
Joe D'Andrea
I have the same problem as jdandrea. That `didSelectRowAtIndexPath` doesn't fire if you tap the TableView itself.
zekel
A: 

Why do you want to create a table full of textfields? You should be using a detailed view for each row that contains the text fields. When you push your detailedview, ensure that you call "[myTextField becomeFirstResponder]" so that the user can start editing with just one click away from the table list.

Mugunth Kumar
Apple's Contacts app does precisely this. I wouldn't say it's *full* of text fields per se, but it does use them to good effect.
Joe D'Andrea
Editing text inline in a tableview is much quicker and more intuitive than pushing detail views for every text field the user wants to edit ... just ask your nearest HTML form, or the text fields in iPhone Preferences panes, or the Contacts app, or etc etc etc ... it's a real shame that Apple hasn't made this a standard cell type, but there is much info on the web about achieving this.
glenc
A: 

If you're willing to subclass (ugh!) your table view, something like this might work:

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

   BOOL backgroundTouched = YES;

   for (UITouch *touch in touches) {
      CGPoint location = [touch locationInView:self];
      for (UITableViewCell *cell in self.visibleCells) {
         if (CGRectContainsPoint(cell.frame, location)) {
            backgroundTouched = NO;
            break;
         }
      }
   }

   if (backgroundTouched) {
      for (UITableViewCell *cell in self.visibleCells) {
         // This presumes the first subview is the text field you want to resign.
         [[cell.contentView.subviews objectAtIndex:0] resignFirstResponder];
      }
   }

   [super touchesBegan:touches withEvent:event];
}
Joe D'Andrea
+2  A: 
@interface DismissableUITableView : UITableView {
}
@end

@implementation DismissableUITableView

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

@end

Then make sure that in your Nib file you set the type of your UITableView to DismissableUITableView .....maybe i could have thought of a better name for this class, but you get the point.

bandejapaisa
A: 

UITableView is a subclass of UIScrollView.

The way I did it was to listen for a scroll event by the user and then resignFirstResponder. Here's the UIScrollViewDelegate method to implement in your code;

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

When approaching these sorts of problems I've found the best way is to research the delegate protocols for each object and those of the parent classes (in this case UITableViewDelegate, UIScrollViewDelegate. The number of events NS objects fires is quite large and comprehensive. It's also easier implementing a protocol then subclassing anything.

freshfunk