如何检测UICollectionView中单元格的双击

Cri*_*ris 28 objective-c uikit ios uitapgesturerecognizer uicollectionview

我想响应UICollectionView中单元格的双击,并具有双击操作取消单元格选择.

这就是我尝试过的:

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];
Run Code Online (Sandbox Code Playgroud)

也就是说,如果我的双击手势识别器成功,我试图让默认手势识别器失败.

这似乎不起作用,因为我的集合视图委托collectionView:didSelectItemAtIndexPath:仍然在双击后被调用


关于Apple的UICollectionViewController文档的注释

Apple的文档在这一点上有误导性,声称默认手势识别器是UITapGestureRecognizer子类的一个实例,所以可以很容易地选择它[recogniser isKindOfClass:[UITapGestureRecognizer class]].不幸的是,这是一个错误.

Reg*_*ion 46

我不明白你为什么需要requireToFail.我在UICollectionView中使用双击,它不会干扰我的单击(用于选择).

我使用以下内容:

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

那么,这个:

- (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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

似乎工作正常 - 双击被识别,我可以按照我的意愿处理它(在这种情况下,我正在扩展文件夹的内容).但单击将导致选择抽头销售,我没有写任何手势识别.

重要编辑:

我正在重新审视这个问题,因为我已经看到我的原始答案在某些情况下可能是错误的,并且有一个明显的解决方案似乎有效.

需要添加以下行:

doubleTapFolderGesture.delaysTouchesBegan = YES;
Run Code Online (Sandbox Code Playgroud)

这消除了单个抽头对单元选择的干扰.这提供了更强大的设置.


Edw*_*dar 11

这里有很多好的解决方案,但遗憾的是它们对我来说并不可靠(例如我无法通过双击触发,因为我也实现了didSelectItemAtIndexPath).

对我有用的是将(双)轻击手势识别器添加到集合视图而不是单元格.在它的动作选择器中,我将确定哪个单元被双击并做我需要做的任何事情.希望这有助于某人:

- (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
}
Run Code Online (Sandbox Code Playgroud)


Pau*_*nne 5

我的解决方案是不实现collectionView:didSelectItemAtIndexPath,而是实现两个手势识别器.

    self.doubleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(processDoubleTap:)];
    [_doubleTapGesture setNumberOfTapsRequired:2];
    [_doubleTapGesture setNumberOfTouchesRequired:1];   

    [self.view addGestureRecognizer:_doubleTapGesture];

    self.singleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(processSingleTap:)];
    [_singleTapGesture setNumberOfTapsRequired:1];
    [_singleTapGesture setNumberOfTouchesRequired:1];
    [_singleTapGesture requireGestureRecognizerToFail:_doubleTapGesture];

    [self.view addGestureRecognizer:_singleTapGesture];
Run Code Online (Sandbox Code Playgroud)

这样我可以处理单击和双击.我能看到的唯一问题是单元格是在doubleTaps上选中的,但是如果这很烦人,你可以在两个选择器中处理它.


Cri*_*ris 3

默认手势识别器上的调用requireGestureRecognizerToFail:确实有效(也就是说,如果识别到双击,它们的状态将变为 UIGestureRecognizerStateFailed)。

但似乎 UICollectionView 的collectionView:didSelectItemAtIndexPath:委托回调没有考虑到这一点,即。当默认手势识别器失败时仍然会调用它。

因此,答案/解决方法是确保委托collectionView:shouldSelectItemAtIndexPath:collectionView:shouldDeselectItemAtIndexPath:实现检查默认手势识别器(其中之一?)的状态,因此:

- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {

    UITapGestureRecognizer *defaultGestureRecogniser = [[self.collectionView gestureRecognizers] objectAtIndex:0];
    return defaultGestureRecogniser.state != UIGestureRecognizerStateFailed;
}
Run Code Online (Sandbox Code Playgroud)