添加双击到UICollectionView;要求单击才能失败

时间:2013-07-16 08:22:39

标签: uigesturerecognizer uicollectionview uitapgesturerecognizer

问题与this question类似,我正在尝试向我的UICollectionView实例添加双击手势识别器。

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

为了实现这一点,我实现了代码straight from Apple's Collection View Programming Guide (Listing 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]]从未计算为true,因此未建立新tapGesture的失败要求。

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

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

显示默认手势识别器(实际上)不是UITapGestureRecognizer个实例。

相反,它们是私人课程UIScrollViewDelayedTouchesBeganGestureRecognizerUIScrollViewPanGestureRecognizer

首先,如果不违反有关私有API的规则,我无法明确使用这些内容。其次,通过UIScrollViewDelayedTouchesBeganGestureRecognizer附加到requireGestureRecognizerToFail:似乎无法提供所需的行为 - 即代理人的didSelect...仍然被调用。

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

提前致谢!

2 个答案:

答案 0 :(得分: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上选中的,但如果这很麻烦,你可以在两个选择器中处理它。

答案 1 :(得分: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];

通过将delaysTouchesBegan设置为YES,自定义手势识别器优先于默认的集合视图,通过延迟注册其他触摸事件来点击侦听器。或者,您可以通过将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
    }
}