UITapGestureRecognizer-シングルタップとダブルタップ


156

UITapGestureRecognizersビューに2 つ追加しようとしています。1つはシングルタップイベント用、もう1つはダブルタップイベント用です。シングルタップレコグナイザは期待どおりに動作します(それ自体)。しかし、ダブルタップレコグナイザーを機能させることができないようです。

持っては、同様の特性を試してみました:cancelsTouchesInViewdelaysTouchesBeganそしてdelaysTouchesEndedまだ動作しません。

ダブルタップすると、シングルタップ認識機能が常にアクティブになり、ダブルタップイベントもスーパービューに送信されます。しかし、カスタムダブルタップ認識機能はまったく通知されないようです。

ドキュメントは、上記の3つのプロパティを目的に使用できることを示唆しているようです。しかし、どの値を設定し、どのレコグナイザ(シングル、ダブル、または両方)に設定する必要があるのか​​、私にはわかりません。これに精通している誰かが助けてくれることを願っています。

以下は、最新の更新されたコードブロックです。

// ****** gesture recognizers ******

- (void)addSingleAndDoubleTapGestureRecognizersToView:(UIView *)view
{
    // single tap    
    UITapGestureRecognizer *singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget: tableViewController action: @selector(handleSingleTapOnView:)];                                 
    [singleTapRecognizer setNumberOfTouchesRequired:1];
    [view addGestureRecognizer: singleTapRecognizer];

    // double tap 
    UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget: tableViewController action: @selector (handleDoubleTapOnView:)];        
    [doubleTapRecognizer setNumberOfTouchesRequired:2];         
    [singleTapRecognizer requireGestureRecognizerToFail: doubleTapRecognizer];
    [view addGestureRecognizer: doubleTapRecognizer];         
}

- (void)handleSingleTapOnView:(id)sender
{

}

- (void)handleDoubleTapOnView:(id)sender
{

}

30
ランダムなコメント:変数名にアンダースコアを使用すると、ほとんどのObjective-Cプログラマーが不自然になります。さらに悪いことに、変数名は説明的ではありません。なぜsingleTapRecognizerとdoubleTapRecognizer(または類似のもの)を使用しないのですか?入力には数秒かかりますが、コードが無限に読みやすくなります。
UIAdam

アドバイスをありがとう、変数名はよりわかりやすいものにすべきであることに同意します。しかし、この特定のコードセグメントはまだ完成しておらず、提案されているように、より洗練された記述的なコードを投稿します...
スタンレー

他の誰かが同様の問題を抱えている場合。ダブルタップとシングルタップの認識機能を一緒にすばやく動作させるのに苦労しました(シングルタップは問題なく動作しましたが、ダブルタップは動作しませんでした)。ストーリーボードを使用して、認識機能をシーンにドラッグしました。私はハンドラーとステートメントを持っています:viewDidLoad内にsingleTapRecognizer.requireGestureRecognizerToFail(doubleTabRecognizer)がありましたが、それでもダブルタップしていません。私が足りなかったパズルのピースは、ダブルタップが認識されるはずのビューの部分の上に(シーンの一番上の行から)ダブルタップ認識アイコンをドラッグすることでした。
Paulus

1
@UIAdamがアンダースコアを使用してobjcのプライベートivar名にプレフィックスを付けるのは一般的ですが、そうではありませんか?(迅速な背景から)
Charlton Provatas

回答:


412
UITapGestureRecognizer *singleTap = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doSingleTap)] autorelease];
singleTap.numberOfTapsRequired = 1; 
[self.view addGestureRecognizer:singleTap];

UITapGestureRecognizer *doubleTap = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doDoubleTap)] autorelease];
doubleTap.numberOfTapsRequired = 2; 
[self.view addGestureRecognizer:doubleTap];

[singleTap requireGestureRecognizerToFail:doubleTap];

注: 使用し numberOfTouchesRequired ている場合は、 .numberOfTouchesRequired = 1;

Swiftの場合

let singleTapGesture = UITapGestureRecognizer(target: self, action: #selector(didPressPartButton))
singleTapGesture.numberOfTapsRequired = 1
view.addGestureRecognizer(singleTapGesture)

let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(didDoubleTap))
doubleTapGesture.numberOfTapsRequired = 2
view.addGestureRecognizer(doubleTapGesture)

singleTapGesture.require(toFail: doubleTapGesture)

答えてくれてありがとう。コードを試してみましたが、まだ機能しません。まだ見逃しているものがあるに違いない。ヒントはもうありますか?
スタンレー

これの実装ファイルを入手できますか?
Anil Kothari、2012年

@スタンリー:Anilsの回答が機能するはずですが、もちろんハンドラー(doSingleTap、doDoubleTap)も提供する必要があります
Rok Jarc

シングルタップは、期待どおりに機能しているUITableViewを更新します。とりあえず、ダブルタップはNSLogを使用してログステートメントを出力するだけです。私の疑いは、最初のレスポンダーステータスは、最初のタップの後、UIViewから他の場所に移動することです。これは、応答チェーンについて明示的に何もしなかったためです。
スタンレー、

6
解決策は私にとってうまくいきます。シングルタップセレクターは、少し遅れて発生します。
ウラジミール・オブライザン

46

Swift 3ソリューション:

let singleTap = UITapGestureRecognizer(target: self, action:#selector(self.singleTapAction(_:)))
singleTap.numberOfTapsRequired = 1
view.addGestureRecognizer(singleTap)

let doubleTap = UITapGestureRecognizer(target: self, action:#selector(self.doubleTapAction(_:)))
doubleTap.numberOfTapsRequired = 2
view.addGestureRecognizer(doubleTap)

singleTap.require(toFail: doubleTap)

コード行singleTap.require(toFail:doubleTap)では、シングルタップを強制的に待機させ、タップイベントがダブルタップではないことを確認しています。


31

requireGestureRecognizerToFail:メソッドを使用する必要があります。このようなもの:

[singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];


両方のレコグナイザで「Fail」メソッドコールをもう一度使用しようとしました。しかし、それでも機能しません。以前にダブルタップ機能が動作している場合は、その経験をもう少し教えてください。
スタンレー

1
私はこの正確なコード(Anilがより詳細に投稿したものと同じ)を試しましたが、それは私にとってはうまくいきました。
UIAdam 2012年

コメントをありがとう、それでも私が見逃していた何かがまだあるに違いない...
スタンリー

あなたのコードはまだdelaysTouchesや他のものをいじっています。Anilのコードに正確に従うようにします。requireGestureRecognizerToFailは、通常の方法でのみ使用してください。
UIAdam 2012年

私が今のところ時間が足りないので、今日または明日の後であなたが助言したように行います。あなたの親切な援助に感謝します...
スタンリー

15

// ----まず、ダブルタップとシングルタップのジェスチャーを割り当てる必要があります------- //

UITapGestureRecognizer* doubleTap = [[UITapGestureRecognizer alloc] initWithTarget : self action : @selector (handleDoubleTap:)];

UITapGestureRecognizer* singleTap = [[UITapGestureRecognizer alloc] initWithTarget : self action : @selector (handleSingleTap:)];

[singleTap requireGestureRecognizerToFail : doubleTap];
[doubleTap setDelaysTouchesBegan : YES];
[singleTap setDelaysTouchesBegan : YES];

// -----------------------タップ数---------------- //

[doubleTap setNumberOfTapsRequired : 2];
[singleTap setNumberOfTapsRequired : 1];

// -------ビューまたはボタンにダブルタップとシングルタップのジェスチャーを追加する-------- //

[self.view addGestureRecognizer : doubleTap];
[self.view addGestureRecognizer : singleTap];

10

それがまさにあなたが探しているものかどうかはわかりませんが、ジェスチャ認識機能なしでシングル/ダブルタップを行いました。UITableViewで使用しているので、didSelectRowAtIndexPathメソッドでそのコードを使用しました

    tapCount++;
    switch (tapCount)
    {
        case 1: //single tap
            [self performSelector:@selector(singleTap:) withObject: indexPath afterDelay: 0.2];
            break;
        case 2: //double tap
            [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(singleTap:) object:indexPath];
            [self performSelector:@selector(doubleTap:) withObject: indexPath];
            break;
        default:
            break;
    }
    if (tapCount>2) tapCount=0;

メソッドsingleTapおよびdoubleTapは、パラメーターとしてNSIndexPathを指定した場合は無効になります。

- (void)singleTap:(NSIndexPath *)indexPath {
  //do your stuff for a single tap
}

- (void)doubleTap:(NSIndexPath *)indexPath {
  //do your stuff for a double tap
}

それが役に立てば幸い


答えてくれてありがとう、@ Novarg。doubleTap認識エンジンについて私が抱えている問題はありましたか?
スタンレー、

@Stanleyいいえ、singleTapは発砲する前に0.2秒待機しています。その間に2番目のタップがアクティブになった場合、singleTapメソッドはキャンセルされます。
Novarg '17

ご協力いただきありがとうございます。今日も時間切れです。明日はぜひお試しください:)
スタンレー

創造的な答え;)
Michael

非常に良い解決策。次のタッチも確実に認識されるようにするために、各ハンドラー(singleTap、doubleTap)にtapCount = 0を追加する必要がありました。
Sirio

3

Swift 2のソリューション:

let singleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleSingleTap))
singleTapGesture.numberOfTapsRequired = 1 // Optional for single tap
view.addGestureRecognizer(singleTapGesture)

let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
doubleTapGesture.numberOfTapsRequired = 2
view.addGestureRecognizer(doubleTapGesture)

singleTapGesture.requireGestureRecognizerToFail(doubleTapGesture)

1

UIGestureRecognizerDelegateメソッドを実装して、singleTapとdoubleTapの両方を検出しました。

ただこれをする。

 UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleDoubleTapGesture:)];
    [doubleTap setDelegate:self];
    doubleTap.numberOfTapsRequired = 2;
    [self.headerView addGestureRecognizer:doubleTap];

    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleSingleTapGesture:)];
    singleTap.numberOfTapsRequired = 1;
    [singleTap setDelegate:self];
    [doubleTap setDelaysTouchesBegan:YES];
    [singleTap setDelaysTouchesBegan:YES];
    [singleTap requireGestureRecognizerToFail:doubleTap];
    [self.headerView addGestureRecognizer:singleTap];

次に、これらのデリゲートメソッドを実装します。

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
    return  YES;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}

0

一部のビューには、独自のダブルタップ認識機能が組み込まれています(MKMapView例)。これを回避するには、UIGestureRecognizerDelegateメソッドを実装shouldRecognizeSimultaneouslyWithGestureRecognizerして返す必要がありますYES

まず、ダブルおよびシングルレコグナイザーを実装します。

// setup gesture recognizers
UITapGestureRecognizer* singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                                action:@selector(mapViewTapped:)];
singleTapRecognizer.delegate = self;
singleTapRecognizer.numberOfTapsRequired = 1;


UITapGestureRecognizer* doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                                      action:@selector(mapViewDoubleTapped:)];
doubleTapRecognizer.delegate = self;    // this allows
doubleTapRecognizer.numberOfTapsRequired = 2;
[singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];

次に実装します。

#pragma mark UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer
*)otherGestureRecognizer {  return YES; }

-1

@stanleyのコメントに関連して-

UITableViewすでに完全なタップ処理が行われているため、行の選択範囲でタップジェスチャを使用して作業しないでください。

ただし、シングルタップジェスチャリコグナイザで[ビューのタッチのキャンセル]を[いいえ]に設定する必要があります。そうしないと、タップイベントが取得されません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.