web-dev-qa-db-fra.com

Appui long 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?

En particulier, le geste reconnaît sur UITableView?

179
foOg

Ajoutez d’abord le dispositif de reconnaissance des gestes de presse longs à la vue tableau:

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 %ld", indexPath.row);
    } else {
        NSLog(@"gestureRecognizer.state = %ld", gestureRecognizer.state);
    }
}

Vous devez faire attention à ceci afin qu'il n'interfère pas avec le tapotement normal de la cellule par l'utilisateur et notez également que handleLongPress peut se déclencher plusieurs fois (cela sera dû aux changements d'état du programme de reconnaissance de mouvements).

417
user467105

J'ai utilisé la réponse d'Anna-Karenina, et cela fonctionne presque très bien avec un très grave problème.

Si vous utilisez des sections, une pression longue sur le titre de la section vous donnera un résultat erroné 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 factices en fonction de l'état du geste, par défaut). 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);
            }
        }
    }
}
44
marmor

Voici des instructions clarifiées combinant la réponse de Dawn Song à celle de Marmor.

Faites glisser une longue reconnaissance du geste de presse et déposez-la dans votre cellule de tableau. Il sautera au bas de la liste à gauche.

enter image description here

Ensuite, connectez la reconnaissance des gestes de la même manière que vous connecteriez un bouton. enter image description here

Ajoutez le code de Marmor dans le gestionnaire d'actions

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

    CGPoint p = [sender 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);
        }
    }
}

}

19
Ryan Heitner

Réponse in Swift 5 (suite de la réponse de Ricky dans Swift)

Ajoutez le UIGestureRecognizerDelegate à votre ViewController

 override func viewDidLoad() {
    super.viewDidLoad()

    //Long Press
    let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
    longPressGesture.minimumPressDuration = 0.5
    longPressGesture.delegate = self
    self.tableView.addGestureRecognizer(longPressGesture)
 }

Et la fonction:

@objc func handleLongPress(longPressGesture: UILongPressGestureRecognizer) {
    let p = longPressGesture.location(in: self.tableView)
    let indexPath = self.tableView.indexPathForRow(at: p)
    if indexPath == nil {
        print("Long press on table view, not row.")
    } else if longPressGesture.state == UIGestureRecognizer.State.began {
        print("Long press on row, at \(indexPath!.row)")
    }
}
16
Ben

Il semble plus efficace d’ajouter le dispositif de reconnaissance directement à la cellule, comme indiqué ci-dessous:

Appuyez et maintenez pour les cellules TableView, alors et maintenant

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

12
J.R.

Réponse dans Swift:

Ajoutez délégué UIGestureRecognizerDelegate à votre UITableViewController.

Dans UITableViewController:

override func viewDidLoad() {
    super.viewDidLoad()

    let longPressGesture:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "handleLongPress:")
    longPressGesture.minimumPressDuration = 1.0 // 1 second press
    longPressGesture.delegate = self
    self.tableView.addGestureRecognizer(longPressGesture)

}

Et la fonction:

func handleLongPress(longPressGesture:UILongPressGestureRecognizer) {

    let p = longPressGesture.locationInView(self.tableView)
    let indexPath = self.tableView.indexPathForRowAtPoint(p)

    if indexPath == nil {
        print("Long press on table view, not row.")
    }
    else if (longPressGesture.state == UIGestureRecognizerState.Began) {
        print("Long press on row, at \(indexPath!.row)")
    }

}
9
Ricky

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

Comme cela, vous aurez une méthode de délégué pratique, à laquelle vous êtes habitué lorsque vous utilisez des vues de table standard. 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 souhaitez utiliser cela dans un UITableViewController, vous devez probablement sous-classer et vous conformer au nouveau protocole.

Cela fonctionne très bien pour moi, espérons que cela aidera les autres!

6
de.

Swift 3 répond, en utilisant la syntaxe moderne, en intégrant d’autres réponses et en éliminant le code inutile.

override func viewDidLoad() {
    super.viewDidLoad()
    let recognizer = UILongPressGestureRecognizer(target: self, action: #selector(tablePressed))
    tableView.addGestureRecognizer(recognizer)
 }

@IBAction func tablePressed(_ recognizer: UILongPressGestureRecognizer) {
    let point = recognizer.location(in: tableView)

    guard recognizer.state == .began,
          let indexPath = tableView.indexPathForRow(at: point),
          let cell = tableView.cellForRow(at: indexPath),
          cell.isHighlighted
    else {
        return
    }

    // TODO
}
4
phatmann

Ajoutez simplement UILongPressGestureRecognizer à la cellule prototype donnée dans le storyboard, puis transférez le geste dans le fichier .m de viewController pour créer une méthode d'action. Je l'ai fait comme je l'ai dit.

2
DawnSong