6

Z podobnym problemem do this question, próbuję dodać kreator dwukrotnego dotknięcia do instancji UICollectionView.Dodaj podwójne dotknięcie do UICollectionView; wymagać pojedynczego dotknięcia, aby zakończyć się niepowodzeniem

Potrzebuję zapobiec domyślnemu pojedynczemu dotknięciu wywoływania metody UICollectionViewDelegatecollectionView:didSelectItemAtIndexPath:.

W celu osiągnięcia tego zaimplementować kod straight from Apple's Collection View Programming Guide (Listing 4-2):

UITapGestureRecognizer* tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)]; 
NSArray* recognizers = [self.collectionView gestureRecognizers]; 

// Make the default gesture recognizer wait until the custom one fails. 
for (UIGestureRecognizer* aRecognizer in recognizers) { 
    if ([aRecognizer isKindOfClass:[UITapGestureRecognizer class]]) 
     [aRecognizer requireGestureRecognizerToFail:tapGesture]; 
} 

// Now add the gesture recognizer to the collection view. 
tapGesture.numberOfTapsRequired = 2; 
[self.collectionView addGestureRecognizer:tapGesture]; 

Ten kod nie działa zgodnie z oczekiwaniami: tapGesture pożarów na podwójnym kranu ale domyślny pojedynczy kranu nie jest zabroniony, a Metoda delegata didSelect... jest nadal wywoływana.

Krok po kroku w debugerze ujawnia, że ​​warunek if, [aRecognizer isKindOfClass:[UITapGestureRecognizer class]], nigdy nie jest prawdziwy, a zatem nie jest ustalane wymaganie dotyczące awarii w nowym tapGesture.

Uruchomienie tego debugera polecenia za każdym razem za pomocą pętli for:

po (void)NSLog(@"%@",(NSString *)NSStringFromClass([aRecognizer class])) 

pokazuje, że Recognizers domyślny gest są (w rzeczywistości) nie UITapGestureRecognizer przypadkach.

Zamiast tego są to prywatne klasy UIScrollViewDelayedTouchesBeganGestureRecognizer i UIScrollViewPanGestureRecognizer.

Po pierwsze, nie mogę ich używać w sposób jawny, nie łamiąc zasad dotyczących prywatnego interfejsu API. Po drugie, dołączenie do UIScrollViewDelayedTouchesBeganGestureRecognizer poprzez requireGestureRecognizerToFail: wydaje się nie zapewniać pożądanego zachowania w każdym razie - to jest nadal wywoływana didSelect... uczestnika.

Jak mogę pracować z Recognizers domyślny gest UICollectionView „s dodać dwukrotnie, aby widoku zbiórki i zapobiec domyślny jeden z kranu również wypalanie collectionView:didSelectItemAtIndexPath: metodę delegata za?

Z góry dzięki!

+0

nie nie realizuje 'CollectionView: didSelectItemAtIndexPath:' wystarczy? – cahn

+0

@cahn: Obawiam się, że nie - potrzebuję podwójnego dotknięcia oprócz standardowego zachowania. –

+0

[To pytanie] (http://stackoverflow.com/questions/12792661/how-to-detect-double-taps-on-cells-in-a-uicollectionview) wydaje się rozwiązać ten sam problem, który masz. Czy to działa? –

Odpowiedz

4

Moje rozwiązanie polegało na niewdrożeniu metody collectionView: didSelectItemAtIndexPath, ale zaimplementowaniu dwóch rozpoznawania gestów.

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

W ten sposób mogę obsługiwać pojedyncze i podwójne stuknięcia. Jedyne, co widzę, to to, że komórka jest wybierana na doubleTaps, ale jeśli ci to przeszkadza, możesz sobie z tym poradzić w swoich dwóch selektorach.

+0

Dzięki za odpowiedź. Wygląda na to, że to jest droga. –

+0

Nie polecam tego rozwiązania z następujących powodów: 1) Możesz mieć istniejący kod, który już używa wyboru 2) Możesz chcieć wyboru w przyszłości 3) gestRecognizers ma być używany w dowolnych widokach i widokach może mieć całą logikę do obsługi zdarzeń dotykowych. Użycie delaysTouchesBegan/Ended to znacznie bardziej skalowalne rozwiązanie. (Patrz odpowiedź Szilta) –

+0

Zgadzam się, ale w 13 jestem pewny, że próbowałem tego i nigdy nie działałem. Mogę się mylić oczywiście, ale lubię też kod Sz'z. –

4

używam następuje zarejestrowanie UITapGestureRecognizer:

UITapGestureRecognizer* singleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapGesture:)]; 
singleTapGesture.delaysTouchesBegan = YES; 
singleTapGesture.numberOfTapsRequired = 1; // number of taps required 
singleTapGesture.numberOfTouchesRequired = 1; // number of finger touches required 
[self.collectionView addGestureRecognizer:singleTapGesture]; 

Ustawiając delaysTouchesBegan do YES zwyczaj gest rozpoznawania dostaje priorytet w stosunku do słuchaczy kranu widok domyślny zbiórki poprzez opóźnianie rejestrowanie innych zdarzeń dotykowych. Alternatywnie można ustawić anulowanie rozpoznawania dotykowego, ustawiając wartość cancelsTouchesInView na YES.

Gest jest niż obsługiwane przez następującą funkcją:

- (void)handleSingleTapGesture:(UITapGestureRecognizer *)sender { 

    if (sender.state == UIGestureRecognizerStateEnded) { 
     CGPoint location = [sender locationInView:self.collectionsView]; 
     NSIndexPath *indexPath = [self.collectionsView indexPathForItemAtPoint:location]; 

     if (indexPath) { 
      NSLog(@"Cell view was tapped."); 
      UICollectionViewCell *cell = [self.collectionsView cellForItemAtIndexPath:indexPath]; 
      // Do something.     
     } 
    } 
    else{ 
     // Handle other UIGestureRecognizerState's 
    } 
} 
+0

Działa doskonale, nie zmieniając już istniejącego kodu, .delyaTouchesBegan jest drogą do zrobienia. –