我想对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];
也就是说,如果我的双击手势识别器成功,我试图让默认手势识别器失败。
这似乎不起作用,因为我的集合视图委托的collectionView:didSelectItemAtIndexPath:
在双击后仍然被调用
Apple's documentation在这一点上具有误导性,声称默认手势识别器是UITapGestureRecognizer子类的实例,因此可以使用[recogniser isKindOfClass:[UITapGestureRecognizer class]]
轻松选择它。不幸的是,这是一个错误。
答案 0 :(得分:44)
我不明白你为什么需要requireToFail。我在UICollectionView中使用双击,它不会干扰我的单击(用于选择)。
我使用以下内容:
UITapGestureRecognizer *doubleTapFolderGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(processDoubleTap:)];
[doubleTapFolderGesture setNumberOfTapsRequired:2];
[doubleTapFolderGesture setNumberOfTouchesRequired:1];
[self.view addGestureRecognizer:doubleTapFolderGesture];
然后,这个:
- (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;
}
}
}
似乎工作正常 - 双击被识别,我可以按照自己的意愿处理它(在这种情况下,我正在扩展文件夹的内容)。但单击将导致选择抽头销售,我没有写任何手势识别。
重要编辑:
我正在重新审视这个问题,因为我已经看到我的原始答案在某些情况下可能是错误的,并且有一个明显的解决办法似乎有效。
需要添加以下行:
doubleTapFolderGesture.delaysTouchesBegan = YES;
消除了单个抽头对单元选择的干扰。这提供了更强大的设置。
答案 1 :(得分: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
}
答案 2 :(得分: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];
这样我可以处理单击和双击。我能看到的唯一问题是单元格是在doubleTaps上选中的,但如果这很麻烦,你可以在两个选择器中处理它。
答案 3 :(得分: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;
}
答案 4 :(得分:0)
对于希望快速得到答案的读者,这是@RegularExpression和@Edwin Iskandar答案的组合。
在握有collectionView
的控制器中,添加以下行:
private var doubleTapGesture: UITapGestureRecognizer!
func setUpDoubleTap() {
doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(didDoubleTapCollectionView))
doubleTapGesture.numberOfTapsRequired = 2
collectionView.addGestureRecognizer(doubleTapGesture)
// This line delay the single touch message to the collection view.
// Simple touch will be sent only when the double tap recogniser is sure
// this is a simple tap.
// You can remove it if you don't mind having both a simple tap and double
// tap event.
doubleTapGesture.delaysTouchesBegan = true
}
@objc func didDoubleTapCollectionView() {
let pointInCollectionView = doubleTapGesture.location(in: collectionView)
if let selectedIndexPath = collectionView.indexPathForItem(at: pointInCollectionView) {
let selectedCell = collectionView.cellForItem(at: selectedIndexPath)
// Print double tapped cell's path
print(selectedCell)
}
}