代码之家  ›  专栏  ›  技术社区  ›  Ilya Suzdalnitski

如何在uiTableView中检测某个单元格的双击?

  •  34
  • Ilya Suzdalnitski  · 技术社区  · 15 年前

    我怎样才能在 UITableView ?

    如果用户进行了一次触摸,我想执行一个操作;如果用户进行了两次触摸,我想执行另一个操作?我还需要知道触摸的索引路径。

    我怎样才能实现这个目标?

    谢谢。

    14 回复  |  直到 7 年前
        1
  •  31
  •   Paras Joshi    11 年前

    如果不想创建 UITableView ,将计时器与表视图的 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;
        }
    }
    

    高温高压

        2
  •  27
  •   Paras Joshi    11 年前

    在您的 UITableView 类此方法

    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
     {
    
         if(((UITouch *)[touches anyObject]).tapCount == 2)
        {
        NSLog(@"DOUBLE TOUCH");
        }
        [super touchesEnded:touches withEvent:event];
    }
    
        3
  •  9
  •   Paras Joshi    11 年前

    在你 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];
    }
    
        4
  •  9
  •   shim    8 年前

    第一定义:

    int tapCount;
    NSIndexPath *tableSelection;
    

    作为类级变量在.h文件中进行所有必要的设置。然后…

    - (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;
    }
    
        5
  •  6
  •   WrightsCS    13 年前
    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调用选择器,而不是使用计时器。这解决了@v1ru8提到的问题。

        6
  •  6
  •   Paras Joshi    11 年前

    我选择通过重写 UITableViewCell .

    我的表视图单元格.h

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

    我的表视图单元格.m

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

    表视图控制器.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");
       }
    }
    
        7
  •  2
  •   Cyklet    10 年前

    另一个答案

    int touches;
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
      touches++;
    
        if(touches==2){
           //your action
        }
    }
    
    - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        touches=0;
    }
    
        8
  •  1
  •   Paras Joshi    11 年前

    您可能需要子类 UITableView 并覆盖任何合适的触摸事件( touchesBegan:withEvent ; touchesEnded:withEvent 等)检查事件以查看有多少触摸,并执行自定义行为。别忘了打电话给 UITableView's 触摸方法,否则将无法获得默认行为。

        9
  •  1
  •   Roman Barzyczak    9 年前

    根据@losttintransit,我用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;
        }
    }
    
        10
  •  1
  •   Kamil Harasimowicz    8 年前

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

    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)
        }
    }
    
        11
  •  0
  •   newenglander Ck.Nitin    11 年前

    注意:请看下面的评论,虽然这个解决方案对我有效,但它仍然不是一个好主意。

    创建子类的替代方法 UITableView UITableViewCell (和使用计时器)只是为了延长 UITababVIEW单元格 例如,用一个类别初始化(使用@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
    

    这样,您就不必重新命名现有的 UITababVIEW单元格 使用新的类名(将扩展类的所有实例)。

    注意现在 super 在这种情况下(这是一个类别),不指 UITababVIEW 但对于它的超级, UITView . 但是实际的方法调用 touchesEnded:withEvent: 是在 UIResponder (两者兼而有之) UITVIEW UITababVIEW单元格 是子类),所以没有区别。

        12
  •  0
  •   grigb    10 年前

    以下是我的完整解决方案:

    自定义表视图.h

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

    自定义表视图.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
    
        13
  •  0
  •   Community T.Woody    7 年前

    改进 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];
    }
    
        14
  •  -1
  •   eQmn    7 年前

    此解决方案仅适用于uiCollectionView或uiTableView的单元格。

    首先声明这些变量

    int单击次数;

    布尔线程启动;

    然后将此代码放入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非常适合检测这种类型的点击。现在,您只能分别检测到一次单击和两次单击。祝你好运