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.
Proszę wyjaśnić zmienne finalX, Y i _firstX, Y. Przyda mi się. – arunit21
_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