30

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 の UICollectionViewController ドキュメントに関する注意

Apple のドキュメントはこの点で誤解を招き、デフォルトのジェスチャ レコグナイザーは UITapGestureRecognizer サブクラスのインスタンスであるため、 で簡単に選択できると主張しています[recogniser isKindOfClass:[UITapGestureRecognizer class]]。残念ながら、これはエラーです。

4

5 に答える 5

51

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;
        }
    }
}

正常に動作しているようです-ダブルタップが認識され、思い通りに処理できます(この場合、フォルダーの内容を展開しています)。しかし、1 回タップすると、タップされた販売が選択されます。これについては、ジェスチャ認識については何も書いていません。

重要な編集:

特定の状況では元の回答が間違っている可能性があり、機能しているように見える修正があることがわかったため、この質問を再検討しています。

次の行を追加する必要があります。

doubleTapFolderGesture.delaysTouchesBegan = YES;

これにより、セル選択のためのシングル タップとの干渉がなくなります。これにより、はるかに堅牢なセットアップが提供されます。

于 2013-03-07T08:44:17.867 に答える
13

ここにはたくさんの良い解決策がありますが、残念ながらそれらは私にとっては確実に機能しませんでした (たとえば、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
}
于 2014-03-19T20:38:20.293 に答える
5

私の解決策は、collectionView:didSelectItemAtIndexPath を実装するのではなく、2 つのジェスチャ認識エンジンを実装することでした。

    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];

このようにして、シングルタップとダブルタップを処理できます。私が見ることができる唯一の落とし穴は、セルがダブルタップで選択されていることですが、これが気になる場合は、2 つのセレクターで処理できます。

于 2013-08-03T16:35:29.543 に答える
3

デフォルトのrequireGestureRecognizerToFail:ジェスチャ レコグナイザーで呼び出されたものは実際に機能します (つまり、ダブルタップが認識されると、その状態は UIGestureRecognizerStateFailed になります)。

しかし、UICollectionView のcollectionView:didSelectItemAtIndexPath:デリゲート コールバックはこれを考慮していないようです。デフォルトのジェスチャ認識機能が失敗した場合でも呼び出されます。

したがって、答え/回避策は、デリゲートcollectionView:shouldSelectItemAtIndexPath:collectionView:shouldDeselectItemAtIndexPath:実装がデフォルトのジェスチャ認識機能 (の 1 つ) の状態を確認することです。

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

    UITapGestureRecognizer *defaultGestureRecogniser = [[self.collectionView gestureRecognizers] objectAtIndex:0];
    return defaultGestureRecogniser.state != UIGestureRecognizerStateFailed;
}
于 2012-10-10T05:44:18.823 に答える