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
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
}
}
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))
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))
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
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
}
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];
}
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;
}
}
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