![](/img/trans.png)
[英]How to respond only to a single-tap gesture while letting objects behind respond to double-taps?
[英]How to detect double-taps on cells in a 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];
也就是說,如果我的雙擊手勢識別器成功,我試圖讓默認手勢識別器失敗。
這似乎不起作用,因為我的集合視圖委托的collectionView:didSelectItemAtIndexPath:
仍然在雙擊后被調用
Apple的文檔在這一點上有誤導性,聲稱默認手勢識別器是UITapGestureRecognizer子類的實例,因此可以使用[recogniser isKindOfClass:[UITapGestureRecognizer class]]
輕松選擇它。 不幸的是,這是一個錯誤。
我不明白你為什么需要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;
這消除了單個抽頭對單元選擇的干擾。 這提供了更強大的設置。
這里有很多好的解決方案,但遺憾的是它們對我來說並不可靠(例如我無法通過雙擊觸發,因為我也實現了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
}
我的解決方案是不實現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上選中的,但如果這很麻煩,你可以在兩個選擇器中處理它。
requireGestureRecognizerToFail:
在默認手勢識別器上調用確實有效(即,如果識別出雙擊,則其狀態將轉到UIGestureRecognizerStateFailed)。
但似乎UICollectionView的collectionView:didSelectItemAtIndexPath:
委托回調沒有考慮到這一點,即。 當默認手勢識別器失敗時,它仍會被調用。
所以答案/解決方法是確保委托的collectionView:shouldSelectItemAtIndexPath:
和collectionView:shouldDeselectItemAtIndexPath:
implements檢查默認手勢識別器的狀態(?之一),因此:
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
UITapGestureRecognizer *defaultGestureRecogniser = [[self.collectionView gestureRecognizers] objectAtIndex:0];
return defaultGestureRecogniser.state != UIGestureRecognizerStateFailed;
}
對於尋求快速回答的讀者來說,這是@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)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.