17

Chciałbym połączyć UILongPressGestureRecognizer z UIPanGestureRecognizer.Łączenie UILongPressGestureRecognizer z UIPanGestureRecognizer

UIPanGestureRecognizer powinien rozpoczynać się długim naciśnięciem. Czy istnieje prosty sposób na zrobienie tego? czy naprawdę muszę napisać własny aparat do rozpoznawania gestów?

Chyba coś takiego na ekranie głównym. Naciskasz ikonę i po pewnym czasie ikony zaczynają się chybotać. Następnie, nie wypuszczając palca z ekranu, mogę zacząć przeciągać ikonę pod moim palcem.

Odpowiedz

16

znalazłem rozwiązanie: Ta metoda UIGestureRecognizerDelegate robi dokładnie to, czego szukałem:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer 
20

faktycznie, nie trzeba łączyć rozpoznawania, czyli recognizers gest - można to zrobić wyłącznie z UILongPressGestureRecognizer ... Ty wejdź do StateBegan po tym, jak twoje dotknięcia pozostaną w "dozwolonym ruchu" dla "minimalPressDuration". Pozostajesz w ciągłym longPressGesture, dopóki nie podnosisz żadnego z palców - możesz więc zacząć przesuwać palce i śledzić ruch przez StateChanged.

Gesty długiego naciśnięcia są ciągłe. Gest rozpoczyna się (UIGestureRecognizerStateBegan), gdy liczba dozwolonych palców (numberOfTouchesRequired) została naciśnięta przez określony czas (minimumPressDuration), a dotknięcia nie wykraczają poza dopuszczalny zakres ruchu (dozwolony ruch). Rozpoznawanie gestów przechodzi w stan Zmień, gdy palec się rusza, a kończy (UIGestureRecognizerStateEnded), gdy którykolwiek z palców zostanie uniesiony.

+3

istnieje wiele kwestii, które można uruchomić na chociaż. Jedną z najlepszych rzeczy na temat UIPanGestureRecognizer jest to, że pozwala przesuwać całe okno i wciąż zwraca wartości, podczas gdy UILongPressGestureRecognizer nie pozostawia subskrybentów (przynajmniej tych z ClipsToBounds). – Kpmurphy91

+1

Również brak "prędkości" jest dostępne w momencie poruszania się a LongPress –

15

Miałem trochę problemów z tym problemem. Przyjęta odpowiedź nie była wystarczająca. Bez względu na to, co wstawię w tej metodzie, zostaną wywołane operatory pan lub longpress. Rozwiązanie znalazłem się następująco:

  1. Zapewnienie delegatów aparatów rozpoznawania gestu są przypisane do tej samej klasy (w moim przypadku ja) i upewnić się, że klasa delegat jest UIGestureRecognizerDelegate.
  2. Dodaj następującą metodę delegata do swojej klasy (jak na odpowiedź powyżej):

    - (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
    shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { 
        return YES; 
    } 
    
  3. Dodaj następującą metodę delegata do swojej klasie:

    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { 
        if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && ! shouldAllowPan) { 
          return NO; 
        } 
        return YES; 
    } 
    
  4. Następnie dodać albo właściwość lub ivar, który śledzi, czy patelnia powinna mieć możliwość rozpoczęcia (patrz metoda powyżej). W moim przypadku BOOL shouldAllowPan.

  5. Ustaw BOOL na NO w swoim init lub viewDidLoad. Wewnątrz programu obsługi longPress ustaw BOOL na YES.Robię to tak:

    - (void) longPressHandler: (UILongPressGestureRecognizer *) gesture { 
    
        if(UIGestureRecognizerStateBegan == gesture.state) { 
         shouldAllowPan = NO; 
        } 
    
        if(UIGestureRecognizerStateChanged == gesture.state) { 
         shouldAllowPan = YES; 
        } 
    } 
    
  6. Wewnątrz Panhandler robię czek na BOOL:

    - (void)panHandler:(UIPanGestureRecognizer *)sender{ 
        if(shouldAllowPan) { 
          // do your stuff 
        } 
    
  7. I wreszcie zresetować BOOL obrębie Panhandler:

    else if(sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled) { 
        shouldAllowPan = NO; 
    } 
    
  8. A potem idź po piwo i pogratuluj sobie. ;)

+1

+1. Te kroki naprawdę pomogły mi rozwiązać cel op: pozwolić tylko na przeciąganie po długim naciśnięciu. Tylko 2 komentarze: w kroku 5 wystarczy sprawdzić "Rozpocznij", a następnie ustawić na "TAK". '' \t if (UIGestureRecognizerStateBegan == gesture.state) { \t \t self.shouldAllowDrag = tak; \t} '' ' A w kroku 6. nie trzeba sprawdzać, czy' shouldAllowPan'. - przepraszam za niesformatowany kod. –

+1

Zaimplementowałem rozwiązanie Andy'ego i działało pięknie. Aby uzyskać odpowiedni czas reakcji, zmieniłem również minimalny czas trwania długiego naciśnięcia: UILongPressGestureRecognizer * lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget: self action: @selector (handleLongPressGesture :)]; lpgr.delegate = self; lpgr.minimumPressDuration = 0,05; – chmaynard

+1

To bardzo mi pomogło. Dzięki! Dodam rozwiązanie Swift, aby mogło pomóc innym. – duyn9uyen

5

podejście Andy B w Swift,

  1. Dodaj UIGestureRecognizerDelegate delegata do klasy

    class ViewController: UIViewController, UIGestureRecognizerDelegate 
    
  2. Dodaj zmienną składową

    var shouldAllowPan: Bool = false 
    
  3. Dodaj gesty i musisz dodać delegata gestu panoramowania do VC. Jest to konieczne, aby wystrzelić funkcje shouldRecognizeSimultaneouslyWithGestureRecognizer i gestureRecognizerShouldBegin

    // long press 
    let longPressRec = UILongPressGestureRecognizer(target: self, action: "longPress:") 
    yourView.addGestureRecognizer(longPressRec) 
    
    // drag 
    let panRec = UIPanGestureRecognizer(target: self, action: "draggedView:") 
    panRec.delegate = self 
    yourView.addGestureRecognizer(panRec) 
    
  4. umożliwiają jednoczesne gesty

    func gestureRecognizer(UIGestureRecognizer, 
    shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) -> Bool { 
        // println("shouldRecognizeSimultaneouslyWithGestureRecognizer"); 
        return true 
    } 
    
    func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool { 
        // We only allow the (drag) gesture to continue if it is within a long press 
        if((gestureRecognizer is UIPanGestureRecognizer) && (shouldAllowPan == false)) { 
         return false; 
        } 
        return true; 
    } 
    
  5. Wewnątrz długie naciśnięcie Handler:

    func longPress(sender: UILongPressGestureRecognizer) { 
    
        if(sender.state == .Began) { 
         // handle the long press 
        } 
        else if(sender.state == .Changed){ 
         shouldAllowPan = true 
    
        } 
        else if (sender.state == .Ended) { 
         shouldAllowPan = false 
        } 
    } 
    
+3

Zapomniałeś 6.Weź piwo. :) :) –

+1

@ duyn9uyen Dzięki za konwersję do Swift. –

+0

@ duyn9uyen Dzięki za nawrócenie i to działało jak czar. – aznelite89