views:

2725

answers:

5
+4  Q: 

Detect double tap

Hi,

How can I detect a double tap on a certain cell in UITableView?

i.e. I want to perform one action if the user made a single touch and another if a user made a double touch? I also need to know an index path where the touch was made.

How can I achieve this goal?

Thanks.

+1  A: 

You'll probably need to subclass UITableView and override whatever touch events are appropriate (touchesBegan:withEvent;, touchesEnded:withEvent, etc.) Inspect the events to see how many touches there were, and do your custom behavior. Don't forget to call through to UITableView's touch methods, or else you won't get the default behavior.

zpasternack
+6  A: 

Override in your UITableView class this method

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

     if(((UITouch *)[touches anyObject]).tapCount == 2)
    {
 NSLog(@"DOUBLE TOUCH");
    }
    [super touchesEnded:touches withEvent:event];
}
oxigen
Could you please explain me how do I exactly override the method?I created an object which inherits from UITableView and added a method you recommended. But this method doesn't get called. Thanks.
Ilya
Not to necropost per se, but this is exactly the sort of thing I was looking for - thanks! Only one gotcha for me. What if the UITableView in question is the one within the UITabBar's moreNavigationController? :(
Joe D'Andrea
+2  A: 

If you do not want to create a subclass of UITableView, use a timer with the table view's didSelectRowAtIndex:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    //checking for double taps here
    if(tapCount == 1 && tapTimer != nil && tappedRow == indexPath.row){
     //double tap - Put your double tap code here
     [tapTimer invalidate];
     [self setTapTimer:nil];

     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Double Tap" message:@"You double-tapped the row" delegate:self cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
     [alert show];
     [alert release];
    }
    else if(tapCount == 0){
     //This is the first tap. If there is no tap till tapTimer is fired, it is a single tap
     tapCount = tapCount + 1;
     tappedRow = indexPath.row;
     [self setTapTimer:[NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(tapTimerFired:) userInfo:nil repeats:NO]];
    }
    else if(tappedRow != indexPath.row){
     //tap on new row
     tapCount = 0;
     if(tapTimer != nil){
      [tapTimer invalidate];
      [self setTapTimer:nil];
     }
    }
}

- (void)tapTimerFired:(NSTimer *)aTimer{
    //timer fired, there was a single tap on indexPath.row = tappedRow
    if(tapTimer != nil){
     tapCount = 0;
     tappedRow = -1;
    }
}

HTH

lostInTransit
Many thanks, that's what I ended up with.
Ilya
Would you mind posting more of your code. Where are you setting the tapTimer, tappedRow, and tapCount? Thanks!
Jonah
+1  A: 
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

If I double tab this method it got called twice. Once with tab count 1 and a second time with tab count 2. But i want to detect is it a single tap OR double tap. When I get the 1 tap I don't know if there is following a second tap. How do i detect and decide the action on single or double tap?

V1ru8
A: 

In your UITableView subclass, do something like this:

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    for (UITouch* touch in touches) {
        if (touch.tapCount == 2)
        {
            CGPoint where = [touch locationInView:self];
            NSIndexPath* ip = [self indexPathForRowAtPoint:where];
            NSLog(@"double clicked index path: %@", ip);

            // do something useful with index path 'ip'
        }
    }

    [super touchesEnded:touches withEvent:event];
}
TheSoundOfMatt