194 votes

Appuyez longuement sur UITableView

Je voudrais gérer un appui long sur un UITableViewCell pour imprimer un "menu d'accès rapide". Est-ce que quelqu'un a déjà fait ça?

Particulièrement le geste reconnaît sur UITableView ?

434voto

Anna Points 44332

Ajoutez d'abord le reconnaisseur de gestes de longue pression à la vue de la table:

 UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc] 
  initWithTarget:self action:@selector(handleLongPress:)];
lpgr.minimumPressDuration = 2.0; //seconds
lpgr.delegate = self;
[self.myTableView addGestureRecognizer:lpgr];
[lpgr release];
 

Puis dans le gestionnaire de gestes:

 -(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
    CGPoint p = [gestureRecognizer locationInView:self.myTableView];

    NSIndexPath *indexPath = [self.myTableView indexPathForRowAtPoint:p];
    if (indexPath == nil) {
        NSLog(@"long press on table view but not on a row");
    } else if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
        NSLog(@"long press on table view at row %d", indexPath.row);
    } else {
        NSLog(@"gestureRecognizer.state = %d", gestureRecognizer.state);
    }
}
 

Vous devez être prudent avec ceci afin qu'il n'interfère pas avec le tapement normal de l'utilisateur de la cellule et notez également que handleLongPress peut tirer plusieurs fois avant que l'utilisateur lève le doigt.

46voto

marmor Points 4559

J'ai utilisé la réponse d'Anna-Karenina, et cela fonctionne presque parfaitement avec un bug très sérieux.

Si vous utilisez des sections, en appuyant longuement sur le titre de la section vous obtiendrez un mauvais résultat en appuyant sur la première ligne de cette section, j'ai ajouté une version corrigée ci-dessous (y compris le filtrage des appels fictifs basé sur l'état du Suggestion d'Anna-Karenina).

 - (IBAction)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {

        CGPoint p = [gestureRecognizer locationInView:self.tableView];

        NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
        if (indexPath == nil) {
            NSLog(@"long press on table view but not on a row");
        } else {
            UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
            if (cell.isHighlighted) {
                NSLog(@"long press on table view at section %d row %d", indexPath.section, indexPath.row);
            }
        }
    }
}
 

14voto

J.R. Points 119

Il semble plus efficace d'ajouter le module de reconnaissance directement à la cellule comme indiqué ici:

Tap & Hold pour les cellules TableView, hier et aujourd'hui

(faites défiler jusqu'à l'exemple en bas)

6voto

de. Points 442

J'ai mis en place une petite catégorie sur UITableView basée sur l'excellente réponse d'Anna Karenina.

Comme ceci, vous aurez une méthode de délégué pratique comme vous avez l'habitude de faire avec des vues de table normales. Vérifiez-le:

 //  UITableView+LongPress.h

#import <UIKit/UIKit.h>

@protocol UITableViewDelegateLongPress;

@interface UITableView (LongPress) <UIGestureRecognizerDelegate>
@property(nonatomic,assign)   id <UITableViewDelegateLongPress>   delegate;
- (void)addLongPressRecognizer;
@end


@protocol UITableViewDelegateLongPress <UITableViewDelegate>
- (void)tableView:(UITableView *)tableView didRecognizeLongPressOnRowAtIndexPath:(NSIndexPath *)indexPath;
@end



//  UITableView+LongPress.m

#import "UITableView+LongPress.h"

@implementation UITableView (LongPress)
@dynamic delegate;

- (void)addLongPressRecognizer {
    UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
                                          initWithTarget:self action:@selector(handleLongPress:)];
    lpgr.minimumPressDuration = 1.2; //seconds
    lpgr.delegate = self;
    [self addGestureRecognizer:lpgr];
}


- (void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
    CGPoint p = [gestureRecognizer locationInView:self];

    NSIndexPath *indexPath = [self indexPathForRowAtPoint:p];
    if (indexPath == nil) {
        NSLog(@"long press on table view but not on a row");
    }
    else {
        if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
            // I am not sure why I need to cast here. But it seems to be alright.
            [(id<UITableViewDelegateLongPress>)self.delegate tableView:self didRecognizeLongPressOnRowAtIndexPath:indexPath];
        }
    }
}
 

Si vous voulez utiliser ceci dans un UITableViewController, vous devez probablement sous-classer et se conformer au nouveau protocole.

Cela fonctionne très bien pour moi, j'espère que ça aide les autres!

-2voto

Thomas Joulin Points 3425

Utilisez la propriété d'horodatage UITouch dans touchesBegan pour lancer une minuterie ou l'arrêter lorsque touchesEnded a été renvoyée

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X