7

Próbuję odtworzyć zachowanie menu rozwijanego aplikacji Mapy Google dla nowych iOS.Tworzenie slajdu w widoku podobnym do nowej aplikacji Mapy Google na iOS, problemy z wieloma UIPanGestureRecognizer

W zasadzie jest to widok, który można przesuwać, przesuwając w górę do pewnego punktu lub zsuwając się do określonego punktu. Ten widok może również przesuwać się w prawo i w lewo, jak paginowany widok przewijania.

Powinien on przewijać w górę iw dół lub przesuwać się na boki, ale nie jednocześnie w obu kierunkach.

Po wielu badaniach i testach mam coś, co jest blisko, ale nie działa tak, jak trzeba.

Moja implementacja to UIScrollView z ramką 320 x 400 i widokiem zawartości 960 x 400 z przewijanym paginowaniem. Następnie dodaję narzędzie UIPanGestureRecognizer, które obsługuje slajd całego widoku.

Oto handleTouch IBAction z PanRecognizer:

- (IBAction)handlePan:(UIPanGestureRecognizer *)sender { 
NSLog(@"Panning"); 
    CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self.view]; 

    if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateBegan) { 
     _firstX = [[sender view] center].x; 
     _firstY = [[sender view] center].y; 
    } 
    if (!IS_IPHONE_5) { 
     if (_firstY < 216) 
      translatedPoint = CGPointMake(_firstX, 216); 
     else 
      translatedPoint = CGPointMake(_firstX, _firstY+translatedPoint.y); 
    } 
    else { 
     if (_firstY < 307) 
      translatedPoint = CGPointMake(_firstX, 307); 
     else 
      translatedPoint = CGPointMake(_firstX, _firstY+translatedPoint.y); 
    } 
    [[sender view] setCenter:translatedPoint]; 
    if([(UIPanGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) { 
     CGFloat velocityY = (0.2*[(UIPanGestureRecognizer*)sender velocityInView:self.view].y); 

     CGFloat finalX = _firstX; 
     CGFloat finalY = translatedPoint.y + velocityY; 
     if(finalY < _firstY) { 
      if (IS_IPHONE_5) 
       finalY = 307; 
      else 
       finalY = 216; 
     } 
     else if(finalY > _firstY) { 

      if (IS_IPHONE_5) 
       finalY = 605; 
      else 
       finalY = 515; 
     } 

     CGFloat animationDuration = (ABS(velocityY)*.0002)+.2; 
     [UIView beginAnimations:nil context:NULL]; 
     [UIView setAnimationDuration:animationDuration]; 
     [UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; 
     [UIView setAnimationDelegate:self]; 
     [UIView setAnimationDidStopSelector:@selector(animationDidFinish)]; 
     [[sender view] setCenter:CGPointMake(finalX, finalY)]; 
     [UIView commitAnimations]; 
    }} 

Więc w zasadzie, jeśli pan przesuń widok w górę, a nie na boki. Problem z tą metodą handlePan polega na tym, że nie mogę jej sprawić, aby nie pozwalała na przewijanie tekstu wyższego niż punkt. Który to, co usiłuję zrobić z:

if (_firstY < 216) 
      translatedPoint = CGPointMake(_firstX, 216); 
     else 
      translatedPoint = CGPointMake(_firstX, _firstY+translatedPoint.y); 

Największym problemem jest to, że myśli pan UIScrollView gest rozpoznawania operująca pan w tym samym czasie, niż ta, którą dodaje. Co oznacza, że ​​UIScrollView jest przesuwany w górę i na boki w tym samym czasie, jeśli przesuwać widok palcem, przesuwając go również na boki.

To samo dzieje się, gdy próbuję przesuwać się tylko na boki i przesuwać widok o 1 piksel, podczas gdy moja końcówka rozpoznawania skończy się i całkowicie wsuwa widok.

Rozwiązanie, które znalazłem, polega na ustawieniu mojego narzędzia rozpoznawania paneli tak, aby system rozpoznawania UIScrollview nie działał.

[_panGestureRecognizer requireGestureRecognizerToFail: _slideUpScrollView.panGestureRecognizer]; 

Tak więc, kiedy przesuwać na boki, działa i nie przesuwa widoku w górę. Problem polega na tym, że określa się jako nieudany tylko wtedy, gdy zdejmiesz palec i widok nie przewinie się na boki. To, co się dzieje, to to, że nie możesz już przesuwać widoku, ale jeśli wrzucisz go do środka, zrobi to "UIGestureRecognizerStateEnded" i przesunie widok w górę.

Przyjrzałem się tematom UIPanGestureRecognizer i przyjrzałem się kilku opcjom, w tym podklasowaniu mojego urządzenia do rozpoznawania patelni, aby rozpoznawać tylko przesuwane miski, a nie te z boku.

Czy wydaje mi się, że używam właściwej strategii, czy powinienem spojrzeć na nią w inny sposób?

Idealnym rozwiązaniem byłoby zapisanie slajdu z boku, który przesuwa zawartość tylko w poziomie i jest obsługiwany przez UIScrollView, a gdy rejestrowany jest poziomy pan, patrzy tylko w pionie i jest obsługiwany przez mój panreconizer. Takie samo zachowanie przeglądarki Safari w przypadku przewijania w poziomie iw pionie. Chociaż nie wymyśliłem, jak to zaimplementować.

Dzięki za przeczytanie, daj mi znać, co myślisz. Byłoby wspaniale, gdyby wiele aplikacji miało świetne menu, takie jak Mapy Google!

Edycja: wybieram kierowanie na iOS 6.

+0

Proszę wyjaśnić zmienne finalX, Y i _firstX, Y. Przyda mi się. – arunit21

+0

_firstX, Y mają zapisać pozycję początkową po rozpoczęciu panoramowania. Następnie jest porównywany z finalX, Y, aby w razie potrzeby ustawić/zresetować pozycję przewijania. – Blackcode

Odpowiedz

5

OK, wymyśliłem!

Użyłem przykładów z UIPanGestureRecognizer - Only vertical or horizontal, aby ograniczyć panoramowanie do pionowego przewijania w górę iw dół, a także sprawić, że stanie się nieudane podczas panoramowania w poziomie.

Użyłem także: Restricting UIPanGestureRecognizer movement, aby zablokować widok z panoramowania w górę lub w dół.

końcu odwrócić requiresToFail do:

[_slideUpScrollView.panGestureRecognizer requireGestureRecognizerToFail:_panGestureRecognizer]; 

I to działa!

Daj mi znać, jeśli masz pytania lub masz do zaproponowania poprawki!

Dzięki!

+5

Czy możesz opublikować kopię roboczą (próbkę) tej rzeczy? – harshitgupta

Powiązane problemy