6

由于与此问题类似的问题,我正在尝试将双击手势识别器添加到我的UICollectionView实例中。

我需要防止默认单击调用该UICollectionViewDelegate方法collectionView:didSelectItemAtIndexPath:

为了实现这一点,我直接从 Apple 的Collection View Programming Guide(清单 4-2)中实现了代码:

UITapGestureRecognizer* tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
NSArray* recognizers = [self.collectionView gestureRecognizers];

// Make the default gesture recognizer wait until the custom one fails.
for (UIGestureRecognizer* aRecognizer in recognizers) {
   if ([aRecognizer isKindOfClass:[UITapGestureRecognizer class]])
      [aRecognizer requireGestureRecognizerToFail:tapGesture];
}

// Now add the gesture recognizer to the collection view.
tapGesture.numberOfTapsRequired = 2;
[self.collectionView addGestureRecognizer:tapGesture];

此代码未按预期工作:tapGesture双击时触发,但不阻止默认单击,并且didSelect...仍调用委托的方法。

在调试器中单步执行会发现 if 条件 ,[aRecognizer isKindOfClass:[UITapGestureRecognizer class]]永远不会计算为真,因此新的故障要求tapGesture没有建立。

每次通过 for 循环运行此调试器命令:

po (void)NSLog(@"%@",(NSString *)NSStringFromClass([aRecognizer class]))

揭示了默认手势识别器(确实)不是UITapGestureRecognizer实例。

相反,它们是私有类UIScrollViewDelayedTouchesBeganGestureRecognizerUIScrollViewPanGestureRecognizer.

首先,我不能在不违反私有 API 规则的情况下明确使用这些。其次,附加到UIScrollViewDelayedTouchesBeganGestureRecognizer通孔requireGestureRecognizerToFail:似乎无论如何都不能提供所需的行为——即didSelect...仍然调用委托的。

如何使用UICollectionView的默认手势识别器向集合视图添加双击并防止默认单击也触发委托的collectionView:didSelectItemAtIndexPath:方法?

提前致谢!

4

2 回答 2

4

我的解决方案是不实现 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];

这样我就可以处理单击和双击。我能看到的唯一问题是在 doubleTaps 上选择了单元格,但如果这让您感到困扰,您可以在两个选择器中处理它。

于 2013-08-03T17:16:05.150 回答
4

我使用以下内容注册 UITapGestureRecognizer:

UITapGestureRecognizer* singleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapGesture:)];
singleTapGesture.delaysTouchesBegan = YES;
singleTapGesture.numberOfTapsRequired = 1; // number of taps required
singleTapGesture.numberOfTouchesRequired = 1; // number of finger touches required
[self.collectionView addGestureRecognizer:singleTapGesture];

通过设置delaysTouchesBeganYES定义手势识别器,通过延迟注册其他触摸事件,可以优先于默认集合视图点击侦听器。或者,您可以通过将 设置为cancelsTouchesInView来完全取消触摸识别YES

手势然后由以下函数处理:

- (void)handleSingleTapGesture:(UITapGestureRecognizer *)sender {

    if (sender.state == UIGestureRecognizerStateEnded) {
        CGPoint location = [sender locationInView:self.collectionsView];
        NSIndexPath *indexPath = [self.collectionsView indexPathForItemAtPoint:location];

        if (indexPath) {
            NSLog(@"Cell view was tapped.");
            UICollectionViewCell *cell = [self.collectionsView cellForItemAtIndexPath:indexPath];
            // Do something.                
        }
    }
    else{
        // Handle other UIGestureRecognizerState's
    }
}
于 2015-02-03T10:57:07.333 回答