如何检测UITableView中的某个单元格上的双击?

如何检测UITableView的某个单元格上的双击?

如果用户做了一个单一的触摸,而另一个用户做了双重触摸,我想执行一个动作? 我也需要知道触摸的索引path。

我怎样才能达到这个目标?

谢谢。

如果您不想创buildUITableView的子类,请使用具有表视图的didSelectRowAtIndex:的计时器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

在你的UITableView类中覆盖这个方法

 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { if(((UITouch *)[touches anyObject]).tapCount == 2) { NSLog(@"DOUBLE TOUCH"); } [super touchesEnded:touches withEvent:event]; } 

在你的UITableView子类中,做这样的事情:

 - (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]; } 

首先定义:

 int tapCount; NSIndexPath *tableSelection; 

作为.h文件中的类级variables,并进行所有必要的设置。 然后…

 - (void)tableView(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { tableSelection = indexPath; tapCount++; switch (tapCount) { case 1: //single tap [self performSelector:@selector(singleTap) withObject: nil afterDelay: .4]; break; case 2: //double tap [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(singleTap) object:nil]; [self performSelector:@selector(doubleTap) withObject: nil]; break; default: break; } } #pragma mark - #pragma mark Table Tap/multiTap - (void)singleTap { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"Single tap detected" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; tapCount = 0; } - (void)doubleTap { NSUInteger row = [tableSelection row]; companyName = [self.suppliers objectAtIndex:row]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"DoubleTap" delegate:nil cancelButtonTitle:@"Yes" otherButtonTitles: nil]; [alert show]; tapCount = 0; } 
 if([touch tapCount] == 1) { [self performSelector:@selector(singleTapRecevied) withObject:self afterDelay:0.3]; } else if ([touch tapCount] == 2) { [TapEnableImageView cancelPreviousPerformRequestsWithTarget:self selector:@selector(singleTapRecevied) object:self]; } 

使用performSelector调用select器而不是使用定时器。 这解决了@ V1ru8提到的问题。

我select通过覆盖UITableViewCell来实现它。

MyTableViewCell.h

 @interface MyTableViewCell : UITableViewCell @property (nonatomic, assign) int numberOfClicks; @end 

MyTableViewCell.m

 @implementation MyTableViewCell - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *aTouch = [touches anyObject]; self.numberOfClicks = [aTouch tapCount]; [super touchesEnded:touches withEvent:event]; } 

TableViewController.m

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { MyTableViewCell *myCell = (MyTableViewCell*) [self.tableView cellForRowAtIndexPath:indexPath]; NSLog(@"clicks:%d", myCell.numberOfClicks); if (myCell.numberOfClicks == 2) { NSLog(@"Double clicked"); } } 

另一个答案

 int touches; - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { touches++; if(touches==2){ //your action } } - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { touches=0; } 

您可能需要touchesEnded:withEvent UITableView并覆盖任何适合的触摸事件( touchesBegan:withEvent ; touchesEnded:withEvent等)。检查事件以查看有多less触摸,并执行您的自定义行为。 不要忘记调用UITableView's触摸方法,否则你将不会得到默认的行为。

根据@lostInTransit我准备在Swift中的代码

 var tapCount:Int = 0 var tapTimer:NSTimer? var tappedRow:Int? override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { //checking for double taps here if(tapCount == 1 && tapTimer != nil && tappedRow == indexPath.row){ //double tap - Put your double tap code here tapTimer?.invalidate() tapTimer = nil } 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; tapTimer = NSTimer.scheduledTimerWithTimeInterval(0.2, target: self, selector: "tapTimerFired:", userInfo: nil, repeats: false) } else if(tappedRow != indexPath.row){ //tap on new row tapCount = 0; if(tapTimer != nil){ tapTimer?.invalidate() tapTimer = nil } } } func tapTimerFired(aTimer:NSTimer){ //timer fired, there was a single tap on indexPath.row = tappedRow if(tapTimer != nil){ tapCount = 0; tappedRow = -1; } } 

注意:请看下面的评论,看看虽然这个解决scheme为我工作,但它可能不是一个好主意。

创buildUITableViewUITableViewCell (以及使用计时器)的子类的一个替代方法就是扩展UITableViewCell类,例如(在本例中使用@ oxigen的答案,而不是表格):

 @implementation UITableViewCell (DoubleTap) - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { if(((UITouch *)[touches anyObject]).tapCount == 2) { NSLog(@"DOUBLE TOUCH"); } [super touchesEnded:touches withEvent:event]; } @end 

这样你就不必重新命名UITableViewCell现有实例,并使用新的类名(将扩展该类的所有实例)。

请注意,现在super在这种情况下(这是一个类别)不引用UITableView但它的超级, UITView 。 但实际的方法调用touchesEnded:withEvent:UIResponder (其中UITViewUITableViewCell都是子类),所以没有什么区别。

这是我完整的解决scheme:

CustomTableView.h

 // // CustomTableView.h // #import <UIKit/UIKit.h> @interface CustomTableView : UITableView // Nothing needed here @end 

CustomTableView.m

 // // CustomTableView.m // #import "CustomTableView.h" @implementation CustomTableView // // Touch event ended // - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { // For each event received for (UITouch * touch in touches) { NSIndexPath * indexPath = [self indexPathForRowAtPoint: [touch locationInView:self] ]; // One tap happened if([touch tapCount] == 1) { // Call the single tap method after a delay [self performSelector: @selector(singleTapReceived:) withObject: indexPath afterDelay: 0.3]; } // Two taps happened else if ([touch tapCount] == 2) { // Cancel the delayed call to the single tap method [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(singleTapReceived:) object: indexPath ]; // Call the double tap method instead [self performSelector: @selector(doubleTapReceived:) withObject: indexPath ]; } } // Pass the event to super [super touchesEnded: touches withEvent: event]; } // // Single Tap // -(void) singleTapReceived:(NSIndexPath *) indexPath { NSLog(@"singleTapReceived - row: %ld",(long)indexPath.row); } // // Double Tap // -(void) doubleTapReceived:(NSIndexPath *) indexPath { NSLog(@"doubleTapReceived - row: %ld",(long)indexPath.row); } @end 

改进oxigen答案。

 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; if(touch.tapCount == 2) { CGPoint touchPoint = [touch locationInView:self]; NSIndexPath *touchIndex = [self indexPathForRowAtPoint:touchPoint]; if (touchIndex) { // Call some callback function and pass 'touchIndex'. } } [super touchesEnded:touches withEvent:event]; } 

Swift 3解决scheme比较答案。 不需要任何扩展,只需添加此代码。

 override func viewDidLoad() { viewDidLoad() let doubleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap(sender:))) doubleTapGestureRecognizer.numberOfTapsRequired = 2 tableView.addGestureRecognizer(doubleTapGestureRecognizer) let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(sender:))) tapGestureRecognizer.numberOfTapsRequired = 1 tapGestureRecognizer.require(toFail: doubleTapGestureRecognizer) tableView.addGestureRecognizer(tapGestureRecognizer) } func handleTapGesture(sender: UITapGestureRecognizer) { let touchPoint = sender.location(in: tableView) if let indexPath = tableView.indexPathForRow(at: touchPoint) { print(indexPath) } } func handleDoubleTap(sender: UITapGestureRecognizer) { let touchPoint = sender.location(in: tableView) if let indexPath = tableView.indexPathForRow(at: touchPoint) { print(indexPath) } } 

此解决scheme仅适用于UICollectionView或UITableView的单元格。

首先声明这些variables

int number_of_clicks;

BOOL thread_started;

然后把这个代码放在你的didSelectItemAtIndexPath中

 ++number_of_clicks; if (!thread_started) { thread_started = YES; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.25 * NSEC_PER_SEC), dispatch_get_main_queue(),^{ if (number_of_clicks == 1) { ATLog(@"ONE"); }else if(number_of_clicks == 2){ ATLog(@"DOUBLE"); } number_of_clicks = 0; thread_started = NO; }); } 

0.25是两次点击之间的延迟。 我认为0.25是完美的检测这种types的点击。 现在,您只能单独检测一次点击和两次点击。 祝你好运