Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect double-taps on cells in a UICollectionView

I want to respond to double-taps on cells in a UICollectionView, and have a double-tap action cancel cell selection.

This is what I've tried:

UITapGestureRecognizer *tapRecogniser = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)]; tapRecogniser.numberOfTapsRequired = 2;   for (UITapGestureRecognizer *recogniser in [self.collectionView gestureRecognizers]) {     [recogniser requireGestureRecognizerToFail:tapRecogniser]; }  [self.collectionView addGestureRecognizer:tapRecogniser]; 

That is, I am trying to get the default gesture recognisers to fail if my double-tap gesture recogniser succeeds.

This doesn't appear to work, as my collection view delegate's collectionView:didSelectItemAtIndexPath: is still getting called after a double-tap


Note on Apple's UICollectionViewController Docs

Apple's documentation is misleading on this point, claiming that the default gesture recogniser is an instance of a UITapGestureRecognizer subclass, so it can be easily picked out with [recogniser isKindOfClass:[UITapGestureRecognizer class]]. Unfortunately this is an error.

like image 854
Cris Avatar asked Oct 09 '12 04:10

Cris


People also ask

How do I highlight cells in collectionView?

How to use? Just inherit BaseCollectionViewCell . If needed, configure in cell's init or collectionView 's delegate methods. If you don't need highlight effect, just find a method named 'shouldHighlightItemAtIndexPath' in UICollectionViewDelegate and return false or just set cell.

How does UICollectionView work?

The collection view presents items onscreen using a cell, which is an instance of the UICollectionViewCell class that your data source configures and provides. In addition to its cells, a collection view can present data using other types of views.

What is swift UICollectionView?

From apple's documentation, UICollectionView is: An object that manages an ordered collection of data items and presents them using customizable layouts. The name and definition makes it clear, it is a way to display a Collection of UI Views in our app.


2 Answers

I don't see why you need the requireToFail. I use double-taps in a UICollectionView and it doesn't interfere with my single taps (used for selection).

I use the following:

UITapGestureRecognizer *doubleTapFolderGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(processDoubleTap:)]; [doubleTapFolderGesture setNumberOfTapsRequired:2]; [doubleTapFolderGesture setNumberOfTouchesRequired:1]; [self.view addGestureRecognizer:doubleTapFolderGesture]; 

Then, this:

- (void) processDoubleTap:(UITapGestureRecognizer *)sender {     if (sender.state == UIGestureRecognizerStateEnded)     {         CGPoint point = [sender locationInView:collectionView];         NSIndexPath *indexPath = [collectionView indexPathForItemAtPoint:point];         if (indexPath)         {             NSLog(@"Image was double tapped");         }         else          {             DoSomeOtherStuffHereThatIsntRelated;         }     } } 

Seems to working fine -- the double tap is recognized and I can handle it as I wish (in this case I'm expanding the contents of a folder). But a single-tap will cause the tapped sell to be selected, which I haven't written any gesture recognition for.

IMPORTANT EDIT:

I am revisiting this question because I've seen that my original answer can be wrong in certain circumstances, and there is an apparent fix that seems to work.

The following line needs to be added:

doubleTapFolderGesture.delaysTouchesBegan = YES; 

which eliminates interference with the single tap for cell selection. This provides a much more robust setup.

like image 165
RegularExpression Avatar answered Oct 05 '22 11:10

RegularExpression


There are a bunch of good solutions here but unfortunately they didn't work reliably for me (e.g. I could not get the double tap to trigger consistently possibly because I was also implemented didSelectItemAtIndexPath).

What worked for me was adding the (double)tap gesture recognizer to the collection view instead of the cell. In its action selector I would determine which cell was double tapped and do whatever I needed to do. Hopefully this helps someone:

- (void)viewDidLoad {     UITapGestureRecognizer *doubleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didDoubleTapCollectionView:)];     doubleTapGesture.numberOfTapsRequired = 2;     [self.collectionView addGestureRecognizer:doubleTapGesture]; }  - (void)didDoubleTapCollectionView:(UITapGestureRecognizer *)gesture {      CGPoint pointInCollectionView = [gesture locationInView:self.collectionView];     NSIndexPath *selectedIndexPath = [self.collectionView indexPathForItemAtPoint:pointInCollectionView];     UICollectionViewCell *selectedCell = [self.collectionView cellForItemAtIndexPath:selectedIndexPath];      // do something } 
like image 40
Edwin Iskandar Avatar answered Oct 05 '22 11:10

Edwin Iskandar