web-dev-qa-db-fra.com

Appui long sur UICollectionViewCell

Je me demandais comment ajouter un identifiant de geste long à une (sous-classe de) UICollectionView. J'ai lu dans la documentation que c'est ajouté par défaut, mais je ne comprends pas comment. 

Ce que je veux faire, c’est: Appuyez longuement sur une cellule ( j’ai un agenda de github ), obtenez quelle cellule est engagée et faites des choses avec. J'ai besoin de savoir quelle cellule est pressée depuis longtemps. Désolé pour cette question générale, mais je n'ai rien trouvé de mieux sur Google ou SO 

96
Oscar Apeland

Objectif c

Dans votre fichier myCollectionViewController.h, ajoutez le protocole UIGestureRecognizerDelegate.

@interface myCollectionViewController : UICollectionViewController<UIGestureRecognizerDelegate>

dans votre fichier myCollectionViewController.m:

- (void)viewDidLoad
{
    // attach long press gesture to collectionView
    UILongPressGestureRecognizer *lpgr 
       = [[UILongPressGestureRecognizer alloc]
                     initWithTarget:self action:@selector(handleLongPress:)];
    lpgr.delegate = self;
    lpgr.delaysTouchesBegan = YES;
    [self.collectionView addGestureRecognizer:lpgr];
}

-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer.state != UIGestureRecognizerStateEnded) {
        return;
    }
    CGPoint p = [gestureRecognizer locationInView:self.collectionView];

    NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:p];
    if (indexPath == nil){
        NSLog(@"couldn't find index path");            
    } else {
        // get the cell at indexPath (the one you long pressed)
        UICollectionViewCell* cell =
        [self.collectionView cellForItemAtIndexPath:indexPath];
        // do stuff with the cell
    }
}

Rapide

class Some {

    @objc func handleLongPress(gesture : UILongPressGestureRecognizer!) {
        if gesture.state != .Ended {
            return
        }
        let p = gesture.locationInView(self.collectionView)

        if let indexPath = self.collectionView.indexPathForItemAtPoint(p) {
            // get the cell at indexPath (the one you long pressed)
            let cell = self.collectionView.cellForItemAtIndexPath(indexPath)
            // do stuff with the cell
        } else {
            print("couldn't find index path")
        }
    }
}

let some = Some()
let lpgr = UILongPressGestureRecognizer(target: some, action: #selector(Some.handleLongPress))

Swift 4

class Some {

    @objc func handleLongPress(gesture : UILongPressGestureRecognizer!) {
        if gesture.state != .ended { 
            return 
        } 

        let p = gesture.location(in: self.collectionView) 

        if let indexPath = self.collectionView.indexPathForItem(at: p) { 
            // get the cell at indexPath (the one you long pressed) 
            let cell = self.collectionView.cellForItem(at: indexPath) 
            // do stuff with the cell 
        } else { 
            print("couldn't find index path") 
        }
    }
}

let some = Some()
let lpgr = UILongPressGestureRecognizer(target: some, action: #selector(Some.handleLongPress))
199
abbood

Le même code @ code d'abbood pour Swift:

Dans viewDidLoad:

let lpgr : UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "handleLongPress:")
lpgr.minimumPressDuration = 0.5
lpgr.delegate = self
lpgr.delaysTouchesBegan = true
self.collectionView?.addGestureRecognizer(lpgr)

Et la fonction:

func handleLongPress(gestureRecognizer : UILongPressGestureRecognizer){

    if (gestureRecognizer.state != UIGestureRecognizerState.Ended){
        return
    }

    let p = gestureRecognizer.locationInView(self.collectionView)

    if let indexPath : NSIndexPath = (self.collectionView?.indexPathForItemAtPoint(p))!{
        //do whatever you need to do
    }

}

N'oubliez pas le délégué UIGestureRecognizerDelegate

22

Utiliser le délégué de UICollectionView pour recevoir un événement de presse long

Vous devez impliquer la méthode 3 ci-dessous.

//UICollectionView menu delegate
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath{

   //Do something

   return YES;
}
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender{
    //do nothing
    return NO;
}

- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender{
    //do nothing
}
9
liuyuning

Les réponses fournies ici pour ajouter un identificateur de geste longpress personnalisé sont correctes cependant selon la documentation ici : la classe parente de la classe UICollectionView installe un default long-press gesture recognizer pour gérer les interactions de défilement. identifiant par défaut associé à votre vue de collection.

Le code suivant évitera que votre outil de reconnaissance de mouvements personnalisé interfère avec celui par défaut:

UILongPressGestureRecognizer* longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressGesture:)];

longPressGesture.minimumPressDuration = .5; //seconds
longPressGesture.delegate = self;

// Make the default gesture recognizer wait until the custom one fails.
for (UIGestureRecognizer* aRecognizer in [self.collectionView gestureRecognizers]) {
   if ([aRecognizer isKindOfClass:[UILongPressGestureRecognizer class]])
      [aRecognizer requireGestureRecognizerToFail:longPressGesture];
} 
8
tiguero
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];

[cell addGestureRecognizer:longPress];

et ajoutez la méthode comme ceci.

- (void)longPress:(UILongPressGestureRecognizer*)gesture
{
    if ( gesture.state == UIGestureRecognizerStateEnded ) {

        UICollectionViewCell *cellLongPressed = (UICollectionViewCell *) gesture.view;
    }
}
2
satheeshwaran

Pour disposer d'un identifiant de geste externe et ne pas entrer en conflit avec les identifiants de geste internes de UICollectionView, vous devez:

Ajoutez votre identificateur de mouvements, configurez-le et capturez une référence pour celui-ci quelque part (la meilleure option est sur votre sous-classe si vous sous-classez UICollectionView).

@interface UICollectionViewSubclass : UICollectionView <UIGestureRecognizerDelegate>    

@property (strong, nonatomic, readonly) UILongPressGestureRecognizer *longPressGestureRecognizer;   

@end

Remplacer les méthodes d'initialisation par défaut initWithFrame:collectionViewLayout: et initWithCoder: et ajouter une méthode de configuration pour votre reconnaissance de geste longue pression 

@implementation UICollectionViewSubclass

-(instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout
{
    if (self = [super initWithFrame:frame collectionViewLayout:layout]) {
        [self setupLongPressGestureRecognizer];
    }
    return self;
}

-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super initWithCoder:aDecoder]) {
        [self setupLongPressGestureRecognizer];
    }
    return self;
}

@end

Ecrivez votre méthode de configuration pour qu'elle instancie la reconnaissance des gestes avec une pression longue, définissez son délégué, ses dépendances de configuration avec la reconnaissance des gestes UICollectionView (afin que ce soit le geste principal et que tous les autres gestes attendent jusqu'à ce que le geste échoue avant d'être reconnu) et ajoutez le geste à la vue.

-(void)setupLongPressGestureRecognizer
{
    _longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self
                                                                                action:@selector(handleLongPressGesture:)];
    _longPressGestureRecognizer.delegate = self;

    for (UIGestureRecognizer *gestureRecognizer in self.collectionView.gestureRecognizers) {
        if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
            [gestureRecognizer requireGestureRecognizerToFail:_longPressGestureRecognizer];
        }
    }

    [self.collectionView addGestureRecognizer:_longPressGestureRecognizer];
}

N'oubliez pas non plus d'implémenter les méthodes UIGestureRecognizerDelegate qui échouent avec ce geste et permettent une reconnaissance simultanée (vous pouvez ou non avoir besoin de l'implémenter, cela dépend de vos autres identificateurs de mouvements ou des dépendances avec des identificateurs de mouvements internes).

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    if ([self.longPressGestureRecognizer isEqual:gestureRecognizer]) {
        return NO;
    }

    return NO;
}

les informations d'identification pour cela vont à l'implémentation interne de LXReorderableCollectionViewFlowLayout

2
Dmitry Fantastik