I want to handle a tap in a UITableView
not including the cells. In other words, the headers and footers.
I can add a gesture recognizer to the headers (there are no footers), but the space at the bottom of the last section does not respond to a tap.
Instead of adding the gesture recognizers above, I tried adding a gesture recognizer to the table, but it prevents tableView:didSelectRowAtIndexPath:
being called.
I tried all sorts of UIGestureRecognizerDelegate
calls with not much luck.
I finally got that to work by setting cancelsTouchesInView = NO
on the recognizer (I think this was the secret) and implementing gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
in the delegate so that the tableView
got touches and called tableView:didSelectRowAtIndexPath:
The handler has to filter out taps on the cells, but at least it works. (Also, found a bug in UITableView
indexPathForRowAtPoint:point
which returns invalid indexPaths
sometimes.)
My question is: Is there a better way of getting the cell views to prevent touches/gestures getting through to the table? (I will post code if nobody gives me any better ideas.)
If you don't need to understand - what was clicked (footer or header), you can try the following approach.
Add gesture recognizer in viewDidLoad
method.
- (void) tableViewLongPress:(UILongPressGestureRecognizer *)gestureRecognizer {
CGPoint p = [gestureRecognizer locationInView:self.tableView];
NSIndexPath *indexPath = [self.messageTableView indexPathForRowAtPoint:p];
if (indexPath == nil)
NSLog(@"long press on table view but not on a row");
else {
NSLog(@"long press on table view on a row");
}
}
Attention! I haven't tested this code:)
Here is the code that I went with.
1 Add a tap gesture recognizer to the table. Set Cancels touches in view unchecked.
2 Allow the gestures through the table.
#pragma mark - UIGestureRecognizerDelegate
/**
* Prevents the tap gesture recognizer in the table from gobbling taps
* and allows the table to perform tableView:didSelectRowAtIndexPath:
* <p>
* The gesture recognizer must have cancelsTouchesInView == NO to allow
* the touches through to the table.
* <p>
* The action must check that the tap occurred outside of cells.
*
* @see handleTap:
*/
- (BOOL) gestureRecognizer:(UIGestureRecognizer*)recognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)o {
return recognizer.view == self.table;
}
3 Check the tap is not in a cell.
/**
* Filters a tap on the table to those on the headers/footer.
* <p>
* Note, indexPathForRowAtPoint: has a bug and returns valid indexPaths
* for taps in the last section header and table footer. So an extra
* check is made to ensure that the tap was, in fact, in the cell.
*/
- (IBAction) handleTap:(UITapGestureRecognizer*)tap {
if (UIGestureRecognizerStateEnded == tap.state) {
CGPoint point = [tap locationInView:tap.view];
NSIndexPath* index = [self.table indexPathForRowAtPoint:point];
UITableViewCell* cell;
if (index) {
cell = [self.table cellForRowAtIndexPath:index];
point = [tap locationInView:cell];
if (point.y < 0 || point.y >= cell.frame.size.height) {
index = nil;
}
}
if (!index) {
[self.view performSelector:@selector(endEditing:)
withObject:@(YES) afterDelay:0];
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With