Подтвердить что ты не робот

Как я могу обнаружить двойной щелчок по определенной ячейке в UITableView?

Как я могу обнаружить двойной кран в определенной ячейке в UITableView?

i.e. Я хочу выполнить одно действие, если пользователь сделал одно касание, а другой, если пользователь сделал двойной контакт? Мне также нужно знать индексный путь, в котором было сделано касание.

Как я могу достичь этой цели?

Спасибо.

4b9b3361

Ответ 1

Если вы не хотите создавать подкласс 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

Переопределите в своем классе UITableView этот метод

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

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

Ответ 3

В подклассе 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

Сначала определите:

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

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

Я решил реализовать его, переопределив 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");
   }
}

Ответ 7

Другой ответ

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

Вам, вероятно, понадобится подкласс UITableView и переопределить любые события касания (touchesBegan:withEvent;, touchesEnded:withEvent и т.д.). Осмотрите события, чтобы узнать, сколько их было затронуто, и выполните свое обычное поведение. Не забудьте обратиться к методам UITableView's touch, иначе вы не получите поведение по умолчанию.

Ответ 9

В соответствии с @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;
    }
}

Ответ 10

Примечание: см. комментарии ниже, чтобы видеть, хотя, хотя это решение сработало для меня, это может быть не очень хорошая идея.

Альтернативой созданию подкласса UITableView или UITableViewCell (и использованию таймера) было бы просто расширить класс 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 (из которых оба UITView и UITableViewCell являются подклассами), поэтому нет никакой разницы.

Ответ 11

Здесь мое полное решение:

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

Ответ 12

Улучшение 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];
}

Ответ 13

Решение 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)
    }
}

Ответ 14

Это решение работает только для ячейки UICollectionView или UITableView.

Сначала объявите эти переменные

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 идеально подходит для обнаружения этого типа щелчка. Теперь вы можете обнаружить только один клик и два клика отдельно. Удачи