2014-10-28 2 views
4

Я хочу достичь чего-то очень близкого к тому, что делает Google Maps (iOS), и у меня есть некоторые сомнения.Интерактивный переход, такой как Google Maps (iOS)

Но первое, лучшее объяснение и вещи, чтобы принять во внимание:

-------------- -------------- ОТВЕТА

Благодаря вкладу Jugale, здесь находится хранилище, чтобы все могли загружать и тестировать все.

https://github.com/vCrespoP/VCSlidingView

-------------- ORIGINAL ВОПРОС -----------

  • Вы нажмите на точку внутри карте , представление появляется снизу, но затем, когда вы взаимодействуете с этим сводным видом:
  • Обратите внимание, что когда вы тянете немного, навигационная панель уже настроена.
  • Когда вы прокрутите его вверх, вы можете продолжить прокрутку, и внутренняя прокрутка продолжит прокрутку.
  • Когда вы «реверса» действий, чтобы закрыть вид, то PanGesture не запутались с внутренней Scrollview (то же самое для другого способа, Scrollview VS отклонять)

Вот она в действии: enter image description here

Сомнения:

  • Я попытался сделать это в качестве интерактивного перехода (UIPercentDrivenInteractiveTransition) и отделяя карту от детали в 2-х контроллеров, но у меня возникают проблемы с UIPanGestu повторное вмешательство в scrollView.
  • Может быть, лучше сделать это как подзаголовок и обработать все там? Более или менее, как MBPullDownController (Хотя у него есть некоторые проблемы с iOS8) ->https://github.com/matej/MBPullDownController

Итак, кто-нибудь знает какие-либо рамки, сделала это, или знает, как сделать это в хорошем смысле?

Спасибо за ваше время: D

+1

I .. На самом деле это произошло недавно (если я правильно вас понимаю), и это было действительно «уродливо». Решение проблемы scrollview/pan состояло в том, чтобы пересылать соответствующие события из 'scrollview.panGestureRecognizer' в класс, который обрабатывал основной кастрюль, когда прокрутка прокручивалась до самого верха. –

+0

Не могли бы вы опубликовать этот конкретный код, чтобы получить четкое представление? Или все, если вы сегодня чувствуете себя милосердием: P Использовали ли вы интерактивные переходы или subview только в одном контроллере? Я также видел, что в рамках, которые я связал, он использует внутренне «hitTest», а затем пересылает событие касания к одному контроллеру или другому, но я не знаю, возможно ли это в интерактивных переходах. – Sento

+0

Это код работы, поэтому я не думаю, что могу опубликовать все это. Также у меня его нет сейчас, я попробую и фильтрую соответствующие части и отправлю ответ как можно скорее. Что касается других вопросов: наложение - это просто подкласс UIView, и переход использует 'UIKitDynamics' –

ответ

3

Просматривая моей реализации, кажется, следующие условия:

  1. У меня есть подкласс UIViewController, который контроллер представления
  2. У меня есть подкласс из UIView, который является наложением (и впредь с именем «наложение») (на самом деле для меня это UIScrollView, потому что он тоже должен идти вбок, но я попробую и отфильтровать ненужный код)
  3. У меня есть еще один подкласс UIView, который загружает содержимое наложения («содержание обертки»)
  4. Обертка содержания имеет UIScrollView свойство, в котором загружаются все другие виды («представление содержимого»)

Контроллер представления отвечает за инициализацию наложения, установив его исходный кадр (где высота - высота экрана) и передавая ему контент, не более того.

Из этого метода -initWithFrame наложение устанавливает себя с UIDynamicItemBehavior. Он также создает некоторые объекты UICollisionBehavior: один в верхней части экрана и один внизу внизу экрана в правой позиции y, чтобы верхняя часть наложения была частично видимой (как видно в первом кадре вашего GIF). A UIGravityBehavior также настроен для того, чтобы наложение на нижнюю границу столкновений. Конечно, также установлен _animator = [[UIDynamicAnimator alloc....

Наконец:

_pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan)]; 
_pan.delegate = self; 
_pan.cancelsTouchesInView = FALSE; 

Класс наложения также имеет некоторые другие полезные методы, такие как изменение направления силы тяжести, так что покрышка может оказаться привязываются к верхней или нижней части экрана.

Обработчик _pan использует UISnapBehavior, чтобы сохранить наложение перемещения динамически вверх и вниз экрана под пальцем пользователя:

- (void)handlePan 
{ 
    [self handlePanFromPanGestureRecogniser:_pan]; 
} 

- (void)handlePanFromPanGestureRecogniser:(UIPanGestureRecognizer *)pan 
{ 
    CGFloat d = [pan velocityInView:self.superview.superview].y; 

    CGRect r = self.frame; 
    r.origin.y = r.origin.y + (d*0.057); 

    if (r.origin.y < 20) 
    { 
     r.origin.y = 20; 
    } 
    else if (r.origin.y > [UIScreen mainScreen].bounds.size.height - PEEKING_HEIGHT) 
    { 
     r.origin.y = [UIScreen mainScreen].bounds.size.height - PEEKING_HEIGHT; 
    } 

    if (pan.state == UIGestureRecognizerStateEnded) 
    { 
     [self panGestureEnded]; 
    } 
    else if (pan.state == UIGestureRecognizerStateBegan) 
    { 
     [self snapToBottom]; 
     [self removeGestureRecognizer:_tap]; 
    } 
    else 
    { 
     [_animator removeBehavior:_findersnap]; 
     _findersnap = [[UISnapBehavior alloc] initWithItem:self snapToPoint:CGPointMake(CGRectGetMidX(r), CGRectGetMidY(r))]; 
     [_animator addBehavior:_findersnap]; 
    } 
} 

- (void)panGestureEnded 
{ 
    [_animator removeBehavior:_findersnap]; 

    CGPoint vel = [_dynamicSelf linearVelocityForItem:self]; 
    if (fabsf(vel.y) > 250.0) 
    { 
     if (vel.y < 0) 
     { 
      [self snapToTop]; 
     } 
     else 
     { 
      [self snapToBottom]; 
     } 
    } 
    else 
    { 
     if (self.frame.origin.y > (self.superview.bounds.size.height/2)) 
     { 
      [self snapToBottom]; 
     } 
     else 
     { 
      [self snapToTop]; 
     } 
    } 

} 

Обертка содержимого прослушивает прокрутки событий, генерируемых представления содержимого:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView 
{ 
    //this is our fancy way of getting the pan to work when the scrollview is in the way 
    if (scrollView.contentOffset.y <= 0 && _dragging) 
    { 
     _shouldForwardScrollEvents = TRUE; 
    } 

    if (_shouldForwardScrollEvents) 
    { 
     if ([_delegate respondsToSelector:@selector(theContentWrapper:isForwardingGestureRecogniserTouches:)]) 
     { 
      [_delegate theContentWrapper:self isForwardingGestureRecogniserTouches:scrollView.panGestureRecognizer]; 
     } 
    } 
} 

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate 
{ 
    _dragging = FALSE;//scrollviewdidscroll must not be called after this 

    if (scrollView.contentOffset.y <= 0 || _shouldForwardScrollEvents) 
    { 
     if ([_delegate respondsToSelector:@selector(theContentWrapperStoppedBeingDragged:)]) 
     { 
      [_delegate theContentWrapperStoppedBeingDragged:self]; 
     } 
    } 

    _shouldForwardScrollEvents = FALSE; 
} 

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 
{ 
    _dragging = TRUE; 
} 

Как вы можете видеть, когда bool shouldForwardScrollEvents является TRUE, тогда мы отправляем scrollView.panGestureRecognizer делегату обложки содержимого (наложение). Оверлей реализует методы делегата следующим образом:

- (void)theContentWrapper:(TheContentWrapper *)contentWrapper isForwardingGestureRecogniserTouches:(UIPanGestureRecognizer *)contentViewPan 
{ 
    [self handlePanFromPanGestureRecogniser:contentViewPan]; 
} 

- (void)theContentWrapperStoppedBeingDragged:(TheContentWrapper *)contentWrapper 
{ 
    //because the scrollview internal pan doesn't tell use when it's state == ENDED 
    [self panGestureEnded]; 
} 

Надеюсь, что по крайней мере некоторые из них полезны для кого-то!

+0

Я попробую сегодня и дам вам знать, как это получилось, тогда я буду отмечать это как правильно: D Я должен сказать, насколько я благодарен за то, что вы сделали это для совершенно незнакомого человека. Большое вам спасибо Jugale! – Sento

+0

У меня возникли проблемы с объединением кода. Я создал репозиторий с минимальным проектом и вашим кодом, но есть много недостающих переменных, и я не совсем понял взаимодействие между этими представлениями (оверлей + контентное представление). Если вы хотите внести свой вклад, вы более чем приветствуетесь. https://github.com/vCrespoP/VCSlidingView – Sento

+0

@Sento всегда рад помочь - завтра я посмотрю! –