UITapGestureRecognizer - ketukan tunggal dan ketuk ganda

156

Saya mencoba menambahkan 2 UITapGestureRecognizerske tampilan, satu untuk ketukan tunggal dan satu untuk acara ketuk ganda. Pengenal satu ketuk berfungsi seperti yang diharapkan (sendiri). Tapi sepertinya saya tidak bisa mengaktifkan pengenal ketuk ganda.

Telah mencoba bereksperimen dengan sifat seperti: cancelsTouchesInView, delaysTouchesBegandan delaysTouchesEndedtapi masih tidak bekerja.

Saat saya ketuk dua kali, pengenal satu ketukan akan selalu diaktifkan dan acara ketuk ganda juga akan dikirim ke tampilan super. Tetapi pengenal double tap kustom sepertinya tidak diberi tahu sama sekali.

Dokumentasi tampaknya menunjukkan bahwa 3 properti yang disebutkan di atas dapat digunakan untuk tujuan tersebut. Tapi saya tidak yakin nilai apa yang harus ditetapkan dan di mana pengenal (tunggal, ganda atau keduanya). Semoga seseorang yang akrab dengan ini bisa membantu.

Berikut ini adalah blok kode terbaru yang diperbarui.

// ****** 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
{

}
Stanley
sumber
30
Komentar acak: garis bawah pada nama variabel akan membuat sebagian besar programmer Objective-C merasa ngeri. Yang lebih buruk adalah bahwa nama variabel Anda tidak deskriptif. Mengapa tidak menggunakan singleTapRecognizer dan doubleTapRecognizer (atau yang serupa)? Butuh sepersekian detik untuk mengetik, tetapi membuat kode Anda jauh lebih mudah dibaca.
UIAdam
Terima kasih atas sarannya, setuju dengan Anda bahwa nama-nama variabel harus lebih deskriptif. Tetapi segmen kode khusus ini belum selesai dan akan memposting lebih banyak kode yang dipoles dan deskriptif seperti yang disarankan ...
Stanley
Seandainya ada orang lain yang memiliki masalah serupa. Saya berjuang untuk mendapatkan dua ketuk dan satu ketuk pengenal bekerja bersama dalam cepat (satu ketuk bekerja dengan baik, tetapi tidak ada ketuk ganda). Saya menyeret pengenal ke adegan menggunakan papan cerita. Saya memiliki penangan dan pernyataan: singleTapRecognizer.requireGestureRecognizerToFail (doubleTabRecognizer) di dalam viewDidLoad saya, tetapi masih belum ada ketuk ganda. Bagian puzzle saya yang hilang adalah untuk menyeret ikon pengenal ketuk ganda (dari baris atas adegan) ke bagian tampilan tempat ketukan ganda harus dikenali.
Paulus
1
@UIAdam menggunakan garis bawah untuk awalan nama ivar pribadi di objc cukup umum meskipun tidak? (
Berasal

Jawaban:

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

Catatan: Jika Anda menggunakannya numberOfTouchesRequired harus .numberOfTouchesRequired = 1;

Untuk 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
sumber
Terima kasih atas jawabannya, sudah mencoba kode Anda tetapi masih tidak berfungsi. Pasti masih ada sesuatu yang saya lewatkan. Apakah Anda punya petunjuk lagi?
Stanley
dapatkah saya memiliki file implementasi Anda untuk ini?
Anil Kothari
@Stanley: Jawaban Anils harus bekerja, tentu saja Anda juga harus memberikan penangan (doSingleTap, doDoubleTap)
Rok Jarc
Satu ketukan memperbarui UITableView yang berfungsi seperti yang diharapkan. Ketuk dua kali, untuk saat ini, hanya menampilkan pernyataan log menggunakan NSLog. Kecurigaan saya adalah bahwa status responden pertama beralih dari UIView ke tempat lain setelah ketukan pertama karena saya belum melakukan apa pun secara eksplisit tentang rantai respons.
Stanley
6
Solusinya bekerja untuk saya. Pemilih tap tunggal dipecat setelah beberapa penundaan.
Vladimir Obrizan
46

Solusi 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)

Pada baris kode, singleTap.require (toFail: doubleTap), kami memaksa ketukan tunggal untuk menunggu dan memastikan bahwa acara ketukan bukan ketuk ganda.

Surya Kameswara Rao Ravi
sumber
31

Anda perlu menggunakan metode requireGestureRecognizerToFail:. Sesuatu seperti ini:

[singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];

UIAdam
sumber
Telah mencoba menggunakan metode "Gagal", panggil lagi dengan kedua pengenal tadi. Tapi tetap tidak berhasil. Jika Anda berhasil menggunakan dua kali ketuk, silakan bagikan lebih banyak pengalaman Anda dengan saya.
Stanley
1
Saya telah mencoba kode persis ini (sama seperti yang diposting Anil lebih detail) dan berhasil untuk saya.
UIAdam
Terima kasih atas komentarnya, maka pasti masih ada sesuatu yang saya lewatkan pada bagian saya ...
Stanley
Kode Anda masih kacau dengan delaytouches dan yang lainnya. Buat sedemikian rupa sehingga persis mengikuti kode Anil. Hanya gunakan requireGestureRecognizerToFail setelah kami mendapatkannya.
UIAdam
Akan melakukan seperti yang Anda anjurkan hari ini atau besok karena saya kehabisan waktu untuk saat ini. Terima kasih atas bantuan Anda yang baik ...
Stanley
15

// ---- pertama Anda harus mengalokasikan gerakan ketuk ganda dan tunggal ------- //

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

// ----------------------- jumlah ketukan ---------------- //

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

// ------- tambahkan ketuk ganda dan gerakan ketuk tunggal pada tampilan atau tombol -------- //

[self.view addGestureRecognizer : doubleTap];
[self.view addGestureRecognizer : singleTap];
Jaspreet Singh
sumber
10

Tidak yakin apakah itu yang Anda cari, tapi saya melakukan tap tunggal / ganda tanpa pengenal isyarat. Saya menggunakannya dalam UITableView, jadi saya menggunakan kode itu dalam metode 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;

Metode singleTap dan doubleTap hanya batal dengan NSIndexPath sebagai parameter:

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

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

Semoga ini bisa membantu

Novarg
sumber
Terima kasih atas jawabannya, @Novarg. Apakah Anda memiliki masalah yang saya miliki tentang pengenal doubleTap?
Stanley
@ Stanley tidak, singleTap menunggu 0,2 detik sebelum menembak. Dan jika dalam waktu yang bersamaan ketukan kedua diaktifkan, maka metode singleTap dibatalkan.
Novarg
Ini terlihat sangat menjanjikan, terima kasih atas bantuan Anda. Kehabisan waktu hari ini lagi. Pasti akan mencobanya besok :)
Stanley
Jawaban kreatif;)
Michael
solusi yang sangat bagus. Saya hanya perlu menambahkan tapCount = 0 pada setiap handler (singleTap, doubleTap) untuk memastikan bahwa sentuhan berikut juga dikenali.
Sirio
3

Solusi untuk 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)
limfinity
sumber
1

Saya menerapkan metode UIGestureRecognizerDelegate untuk mendeteksi singleTap dan doubleTap.

Lakukan saja ini.

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

Kemudian terapkan metode delegasi ini.

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

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}
Pengembang iPhone
sumber
0

Beberapa tampilan memiliki pengenalan tap ganda yang sudah ada ( MKMapViewmenjadi contoh). Untuk menyiasatinya, Anda perlu menerapkan UIGestureRecognizerDelegatemetode shouldRecognizeSimultaneouslyWithGestureRecognizerdan mengembalikan YES:

Pertama, implementasikan pengenal ganda dan tunggal Anda:

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

Dan kemudian implementasikan:

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

Mengacu pada komentar @ stanley -

Jangan coba-coba dan gunakan gerakan ketuk untuk memilih pilihan untuk bekerja UITableViewkarena sudah memiliki penanganan ketukan penuh ....

Tetapi Anda harus mengatur 'Cancels Touches in View' ke 'NO' pada pengenal gerakan ketukan tunggal Anda atau tidak akan pernah mendapatkan acara ketukan.

Oliver Dungey
sumber