0

i am making a chat application, and in the chat window there are uilabels in uitableviewcells. initially the keyboard will be present but when the user touches on any place on uitableview, i will make the chat window as fullscreen (dissappearing keyboard).

i cant find a way/trick to accomplish this.

i have tried the following method: by using tableview:didselectrowatindexpath, i am able to do it but, user needs to press on an existent uitableviewcell. but i want to understand the press even when uitableview is empty..

note: my chat tableview is interactive e.x. some rows will include image button which need to be pressable, so i cant just put an invisible button onto uitableview.

thank you for your thoughts

Aytunc Isseven

aytunch
  • 1,326
  • 1
  • 16
  • 31

2 Answers2

1

What you want to do is add a gesture recognizer to the UITableView that responds to the appropriate gestures. I would recommend against using UITapGestureRecognizer as the UITableView is already using taps for selecting the cells, so you might want to try the UILongPressGestureRecognizer. I put together a small sample of how you can do this as follows:

In my viewDidLoad I did the following:

UILongPressGestureRecognizer *gesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressFrom:)];
[self.tableView addGestureRecognizer:gesture];

and the handleLongPressFrom: is as follows:

- (void)handleLongPressFrom:(UILongPressGestureRecognizer *)recognizer {
    NSLog(@"handleLongPressFrom: %@", recognizer);
    // Add real code here
}

The full list of gestures can be found here.

Oh, if you did want to still use tap, check out this stack overflow question. I don't know if the method presented works fully, but it'd be a good place to start.


Using UITapGestureRecognizer with a UITableView: Okay, since the tap gesture seems to be the correct one for your use case you can try and do the following. Step 1 is to set up the gesture recognizer as I listed above using the tap gesture instead of the long press gesture.

The code in viewDidLoad is very similar with an important addition ...

UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapFrom:)];
// we need to set the gesture delegate so we can allow the tap to pass through to the
// UITableViewCell if necessary.
gesture.delegate = self;
[self.tableView addGestureRecognizer:gesture];

The handleTapFrom: function is pretty much the same with just the different gesture recognizer as the parameter.

- (void)handleTapFrom:(UITapGestureRecognizer *)recognizer {
    NSLog(@"handleTapFrom: %@", recognizer);
    // Add real code here
}

The major changes to this approach is that we need to implement the UIGestureRecognizerDelegate protocol. Since our goal is to allow the tap gesture to pass through the UITableView to it's subviews (i.e. the UITableViewCell and it's components) we need to implement the gestureRecognizer:shouldRecieveTouch: function. The following implementation should cover what you are attempting.

#pragma mark UIGestureRecognizerDelegate methods
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    // If the view that is touched is not the view associated with this view's table view, but
    // is one of the sub-views, we should not recognize the touch.
    if (touch.view != self.tableView && [touch.view isDescendantOfView:self.tableView]) {
        return NO;
    }
    return YES;
}

The isDescendantOfView: function returns YES if the view it is testing against is the same as the view doing the testing, so we need to accommodate that case separately. You can generify this function by using gestureRecognizer.view instead of self.tableView, but I didn't think it was necessary in this case.

Community
  • 1
  • 1
Chad
  • 890
  • 6
  • 20
  • Thanks Chad, i dont want to use longpress gestures since iphone users dont have a habbit like that. a single tap is what i need. but if i do that, will it override the uitableviewcell taps? is there a way to be able to differiante between uitableview tapgesture and uitableviewcell didselectrowatindexpath? thanks – aytunch May 25 '12 at 14:43
  • Okay, I figured that might be the case. So what you are trying to accomplish is dismissing the keyboard when a user touches outside of it? – Chad May 25 '12 at 15:23
  • Oh, and if you added a Tap gesture to the tableview it would indeed eat the UITableViewCell taps, but there is a work around for that, it just complicates things a bit. – Chad May 25 '12 at 15:37
  • I just updated my answer with a method of allowing the tap gesture to pass through to the UITableViewCell if the tap occurs there. Let me know if this doesn't work/isn't quite what you needed. – Chad May 25 '12 at 15:56
  • i just started applying your answer Chad, i will give feedback soon, thanks – aytunch May 26 '12 at 08:39
  • code works perfect Chad, thanks. but i didnt understand how this line does all the differentiating between tableview and its pressable objects. can u explain? (touch.view != self.tableView && [touch.view isDescendantOfView:self.tableView]) – aytunch May 26 '12 at 08:56
  • The goal of that line is basically "If the view touched is a subview of the UITableView, then we should not recognize the gesture we put on the UITableView and it should be handled normally". Since isDescendantOfView returns: YES if the receiver is an immediate or distant subview of view or if view is the receiver itself; otherwise NO (from the documentation), we need to throw out the case where touch.view and self.tableView are the same (as we want the tap on the table view to react to our gesture recognizer). – Chad May 26 '12 at 21:18
1

The trick is to make your viewController put a tap recognizer on the view but make it always opt out by returning NO from the delegate method "gestureRecognizerShouldBegin". That way gestureRecognizerShouldBegin gets called for every touch on the view, but you don't interfere with the normal event handling of the table.

    - (void)viewDidLoad {
      [super viewDidLoad];
      [self detectTouchesOnView:self.tableView];
    }

    - (void)detectTouchesOnView:(UIView*)theView {
      UITapGestureRecognizer* tapR = [[UITapGestureRecognizer alloc]initWithTarget:nil action:nil];
      tapR.delegate = self;
      [theView addGestureRecognizer:tapR];
    }

    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
       // React to the UITableView being touched E.G. by hiding the keyboard as below.
      [self.view endEditing:YES]; 
      return NO;
    }
w0mbat
  • 2,430
  • 1
  • 15
  • 16