UITapGestureRecognizer - tek dokunuş ve çift dokunuş


156

UITapGestureRecognizersBir görünüme 2 , tek dokunuş ve diğeri çift dokunma etkinlikleri için 2 eklemeye çalışıyorum . Tek dokunuş tanıyıcı beklendiği gibi çalışıyor (kendi başına). Ama çift musluk tanıyıcıyı çalıştıramadım.

Var gibi özelliklere sahip deneme çalıştı: cancelsTouchesInView, delaysTouchesBeganve delaysTouchesEndedama yine de iş yapmaz.

İki kez dokunduğumda, tek dokunuş tanıyıcı her zaman etkinleştirilir ve çift dokunma olayı da süper görünüme gönderilir. Ancak özel çift dokunma tanıyıcı hiç bilgilendirilmiş gibi görünmüyor.

Belgeler, yukarıda belirtilen 3 özelliğin bu amaçla kullanılabileceğini düşündürmektedir. Ancak hangi değerlerin ve hangi tanıyıcıların (tek, çift veya her ikisi) ayarlanması gerektiğinden emin değilim. Umarım buna aşina biri yardımcı olabilir.

Aşağıda en son güncellenen kod bloğu verilmiştir.

// ****** 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
Rastgele yorum: Değişken adlarındaki alt çizgiler çoğu Objective-C programcısının kandırılmasına neden olur. Daha da kötüsü, değişken adlarınızın açıklayıcı olmamasıdır. Neden yalnızca singleTapRecognizer ve doubleTapRecognizer (ya da benzer bir şey) kullanmıyorsunuz? Yazmak bir saniye daha sürüyor, ancak kodunuzu daha okunaklı hale getiriyor.
UIAdam

Tavsiye için teşekkürler, değişken adlarının daha açıklayıcı olması gerektiğini kabul edin. Ancak bu özel kod segmenti tamamlanmadı ve önerildiği gibi daha parlak ve açıklayıcı kod yayınlayacak ...
Stanley

Başka birisinin benzer bir sorunu olması durumunda. Birlikte hızlı çalışan çift musluk ve tek musluk tanıyıcılar almak için mücadele (tek musluk iyi çalışıyor, ancak hiçbir çift musluk). Tanıyıcıları film şeridi kullanarak sahneye sürükledim. Ben işleyicileri ve deyimi vardı: benim görünümDidLoad içinde singleTapRecognizer.requireGestureRecognizerToFail (doubleTabRecognizer), ama yine de hiçbir çift musluk. Bulmacanın eksik parçası, çift musluk tanıyıcı simgesini (sahnenin üst satırından) çift musluğun tanınacağı kısmın üzerine sürüklemekti.
Paulus

1
@UIAdam objc özel bir ivar adı önek için bir alt çizgi kullanarak hayır oldukça yaygındır? (hızlı bir arka plandan geliyor)
Charlton Provatas

Yanıtlar:


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

Not: Eğer kullanıyorsanız numberOfTouchesRequired öyle olmalı .numberOfTouchesRequired = 1;

Swift için

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)

Cevabınız için teşekkürler, kodunuzu denediniz, ancak hala çalışmıyor. Hala özlediğim bir şey olmalı. Başka ipucun var mı?
Stanley

bunun için uygulama dosyanızı alabilir miyim?
Anil Kothari

@Stanley: Anils cevabı işe yaramalı, elbette işleyicileri de sağlamanız gerekiyor (doSingleTap, doDoubleTap)
Rok Jarc

Tek dokunuş beklendiği gibi çalışan bir UITableView güncellemesi yapar. Şimdilik çift dokunma, sadece NSLog kullanarak bir günlük ifadesi çıktılar. Şüphem, ilk yanıtlama durumunun, yanıt zinciriyle ilgili hiçbir şey yapmadığım için ilk musluktan sonra UIView'den başka bir yere gitmesi.
Stanley

6
Çözüm benim için çalışıyor. Bir kez gecikmeden sonra tek kademe seçici ateşlenir.
Vladimir Obrizan

47

Swift 3 çözümü:

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) kod satırında , tek dokunmayı beklemeye ve tap olayının çift dokunma olmadığından emin olmaya zorlarız .


31

RequirGestureRecognizerToFail: yöntemini kullanmanız gerekir. Bunun gibi bir şey:

[singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];


Her iki tanıyıcı ile "Başarısız" yöntem çağrısı şimdi tekrar kullanmaya çalışın. Ama yine de çalışmıyor. Daha önce çalışan çift musluk şeyiniz varsa, lütfen deneyiminizi biraz daha paylaşın.
Stanley

1
Bu tam kodu denedim (Anil'nin daha detaylı olarak yayınladığı gibi) ve benim için çalışıyor.
UIAdam

Yorum için teşekkürler, o zaman hala benim kaçırdığım bir şey olmalı ...
Stanley

Kodunuz hala delaysTouches ve neyle karışmıyor. Bunu Anıl'ın koduna tam olarak uyması için yapın. Sadece sahip olduğumuz şekilde bir kere requirGestureRecognizerToFail kullanın.
UIAdam

Bugün ya da yarın daha sonra tavsiye ettiğim gibi yapacağım. Nazik yardımlarınız için teşekkürler ...
Stanley

15

// ---- öncelikle çift ve tek dokunma hareketini ayırmanız gerekir ------- //

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

// ----------------------- musluk sayısı ---------------- //

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

// ------- görünüm veya düğmeye çift dokunma ve tek dokunma hareketi ekleyin -------- //

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

10

Tam olarak aradığınız şey olup olmadığından emin değilim, ancak jest tanıyıcılar olmadan tek / çift dokunuşlar yaptım. Bunu bir UITableView kullanıyorum, bu yüzden didSelectRowAtIndexPath yönteminde bu kodu kullandım

    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 ve doubleTap yöntemleri sadece parametre olarak NSIndexPath ile geçersizdir:

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

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

Umarım yardımcı olur


Cevabınız için teşekkürler, Novarg. DoubleTap tanıyıcılarla ilgili yaşadığım bir sorunla karşılaştınız mı?
Stanley

@Stanley hayır, singleTap ateş etmeden önce 0.2 saniye bekliyor. Ve bu sırada ikinci musluk etkinleştirilirse, singleTap yöntemi iptal edilir.
Novarg

Yardımınız için çok umut verici görünüyor. Bugün yine zamanım tükeniyor. Kesinlikle yarın bir deneyeceğim :)
Stanley

Yaratıcı cevap;)
Michael

çok iyi bir çözüm. Sadece aşağıdaki dokunuşların da tanındığından emin olmak için her işleyiciye (singleTap, doubleTap) tapCount = 0 eklemem gerekiyordu.
Sirio

3

Swift 2 için çözüm:

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

Hem singleTap hem de doubleTap'ı tespit etmek için UIGestureRecognizerDelegate yöntemlerini uyguladım.

Sadece bunu yap.

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

Sonra bu delege yöntemlerini uygulayın.

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

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

0

Bazı görünümlerde yerleşik kendi çift musluk tanıtıcıları vardır ( MKMapViewörnek olarak). Bunun üstesinden gelmek için UIGestureRecognizerDelegateyöntem uygulamanız shouldRecognizeSimultaneouslyWithGestureRecognizerve geri dönmeniz gerekir YES:

Önce çift ve tek tanıyıcılarınızı uygulayın:

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

Ve sonra uygulayın:

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

-1

@ Stanley'nin yorumuna referansla -

UITableViewZaten tam musluk kullanımı olduğu için çalışmak için seçimleri sıralamak için dokunma hareketlerini kullanmayın.

Ancak, tek dokunma hareketi tanıyıcılarınızda 'Görünümdeki Dokunuşları İptal Et'i' HAYIR 'olarak ayarlamanız gerekir; aksi takdirde, dokunma olayları hiçbir zaman alınmaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.