13

Я занимался новым API перехода на основе iOS 7 и просматривал все учебники/документацию, которые мог найти, но я не могу представить, как это отразится на моем конкретном сценарии.Как завершить интерактивный переход UIViewController?

Так что, по сути, я пытаюсь реализовать это UIPanGestureRecognizer в представлении, где я бы прокрутил вверх и перешел на VC, чей вид будет скользить снизу, пока текущее представление будет скользить вверх, когда я перетаскиваю свой палец выше ,

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

Вот соответствующий код из VC, который соответствует UIViewControllerTransitionDelegate, которая необходима для Венд контроллеров аниматор:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 
    if ([segue.identifier isEqualToString:@"Swipe"]) { 
     NSLog(@"PREPARE FOR SEGUE METHOD CALLED"); 

     UIViewController *toVC = segue.destinationViewController; 
     [interactionController wireToViewController:toVC]; 
     toVC.transitioningDelegate = self; 
     toVC.modalPresentationStyle = UIModalPresentationCustom; 
     } 
} 

#pragma mark UIViewControllerTransition Delegate Methods 

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController: (UIViewController *)presented                 presentingController: (UIViewController *)presenting sourceController:(UIViewController *)source { 
    NSLog(@"PRESENTING ANIMATION CONTROLLER CALLED"); 

    SwipeDownPresentationAnimationController *transitionController = [SwipeDownPresentationAnimationController new]; 
    return transitionController; 
} 

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed { 
    NSLog(@"DISMISS ANIMATION CONTROLLER CALLED"); 

    DismissAnimatorViewController *transitionController = [DismissAnimatorViewController new]; 
    return transitionController; 
} 

- (id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator { 
    NSLog(@"Interaction controller for dimiss method caled"); 

    return interactionController.interactionInProgress ? interactionController:nil; 
} 

ПРИМЕЧАНИЯ: коромысло взаимодействия только увольнение ОК, который почему это в методе interactionControllerForDismissal

Вот код для мультипликатора увольнением, который прекрасно работает, когда я нажимаю на кнопку, чтобы отклонить его:

#import "DismissAnimatorViewController.h" 

@implementation DismissAnimatorViewController 

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext { 
    return 1.0; 
} 

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext { 
    NSTimeInterval duration = [self transitionDuration:transitionContext]; 

    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; 
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; 

    CGRect initialFrameFromVC = [transitionContext initialFrameForViewController:fromVC]; 

    UIView *containerView = [transitionContext containerView]; 

    CGRect screenBounds = [[UIScreen mainScreen] bounds]; 
    NSLog(@"The screen bounds is :%@", NSStringFromCGRect(screenBounds)); 
    toVC.view.frame = CGRectOffset(initialFrameFromVC, 0, screenBounds.size.height); 
    toVC.view.alpha = 0.2; 

    CGRect pushedPresentingFrame = CGRectOffset(initialFrameFromVC, 0, -screenBounds.size.height); 

    [containerView addSubview:toVC.view]; 

    [UIView animateWithDuration:duration 
          delay:0 
     usingSpringWithDamping:0.6 
      initialSpringVelocity:0 
         options:UIViewAnimationOptionCurveEaseIn 
        animations:^{ 
         fromVC.view.frame = pushedPresentingFrame; 
         fromVC.view.alpha = 0.2; 
         toVC.view.frame = initialFrameFromVC; 
         toVC.view.alpha = 1.0; 
        } completion:^(BOOL finished) { 
         [transitionContext completeTransition:YES]; 
        }]; 
} 

@end 

Вот код для UIPercentDrivenInteractiveTransition подкласса, который служит в качестве контроллера взаимодействия:

#import "SwipeInteractionController.h" 

@implementation SwipeInteractionController { 
    BOOL _shouldCompleteTransition; 
    UIViewController *_viewController; 
} 

- (void)wireToViewController:(UIViewController *)viewController { 
    _viewController = viewController; 
    [self prepareGestureRecognizerInView:_viewController.view]; 
} 

- (void)prepareGestureRecognizerInView:(UIView*)view { 
    UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)]; 
    gesture.minimumNumberOfTouches = 1.0; 

    [view addGestureRecognizer:gesture]; 
} 

- (CGFloat)completionSpeed { 
    return 1 - self.percentComplete; 
    NSLog(@"PERCENT COMPLETE:%f",self.percentComplete); 
} 

- (void)handleGesture:(UIPanGestureRecognizer*)gestureRecognizer { 
// CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view.superview]; 
    CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view.superview]; 

    switch (gestureRecognizer.state) { 
     case UIGestureRecognizerStateBegan: 
      // 1. Start an interactive transition! 
      self.interactionInProgress = YES; 
      [_viewController dismissViewControllerAnimated:YES completion:nil]; 
      break; 
     case UIGestureRecognizerStateChanged: { 
      // 2. compute the current position 
      CGFloat fraction = fabsf(translation.y/568); 
      NSLog(@"Fraction is %f",fraction); 
      fraction = fminf(fraction, 1.0); 
      fraction = fmaxf(fraction, 0.0); 
      // 3. should we complete? 
      _shouldCompleteTransition = (fraction > 0.23); 
      // 4. update the animation controller 
      [self updateInteractiveTransition:fraction]; 
      NSLog(@"Percent complete:%f",self.percentComplete); 
      break; 
     } 
     case UIGestureRecognizerStateEnded: 
     case UIGestureRecognizerStateCancelled: { 
      // 5. finish or cancel 
      NSLog(@"UI GESTURE RECOGNIZER STATE CANCELED"); 
      self.interactionInProgress = NO; 
      if (!_shouldCompleteTransition || gestureRecognizer.state == UIGestureRecognizerStateCancelled) { 
       [self cancelInteractiveTransition]; 
       NSLog(@"Interactive Transition is cancled."); 
       } 
      else { 
       NSLog(@"Interactive Transition is FINISHED"); 
       [self finishInteractiveTransition]; 
      } 
      break; 
     } 
     default: 
      NSLog(@"Default is being called"); 
      break; 
    } 
} 

@end 

Еще раз, когда я запускаю код, и теперь я не красть весь путь чтобы целенаправленно отменить переход, я просто получаю вспышку, и мне представлен контроллер вида, на который я хочу провести. Это происходит независимо от того, завершен или отменен переход.

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

+0

Убедитесь в том, чтобы переопределить методы 'UIPercentDrivenInteractiveTransition' для начала, окончания и обновления анимации. Я не вижу, чтобы они были реализованы в любом месте вашего кода. –

+0

Хорошо, попробуем, спасибо. – DanielRak

+1

@AshFurrow: Я прочитал ваш учебник Teehan + Lax о пользовательских переходах, где вы упомянули о переопределении методов 'UIPercentDrivenInteractiveTransition', но то, что я не получаю, является причиной этого. Это необходимо? Я в настоящее время находится в середине реализации без него, и, по общему признанию, я получаю какое-то странное поведение (например, завершающая анимация повторяется снова из процентной доли, на которой заканчивается жест после первого окончания, экран становится черным после интерактивного отмена), но я ' m не на 100% уверен, что это причина. Anyhoo, просто интересно, есть ли у вас причина для переопределений. Благодаря! – Yazid

ответ

21

Здесь я вижу пару проблем, хотя я не могу быть уверен, что они исправит вашу проблему!

Во-первых, UIView завершение анимации блок вашего контроллера анимации имеет следующее:

[transitionContext completeTransition:YES]; 

В то время как он должен вернуться к завершению на основе результата контроллера взаимодействия следующим образом:

[transitionContext completeTransition:![transitionContext transitionWasCancelled]] 

Кроме того, я что если вы сообщите UIPercentDrivenInteractiveTransition, что переход на 100% завершен, он не вызывает блок завершения контроллера анимации. В качестве обходного пути я ограничиваю его до ~ 99.9%

https://github.com/ColinEberhardt/VCTransitionsLibrary/issues/4

Я создал ряд примеров взаимодействия и анимации контроллеров здесь, что вы могли бы найти полезным:

https://github.com/ColinEberhardt/VCTransitionsLibrary

+0

Спасибо за помощь Колин. Я попробовал то, что вы сказали, но все еще есть проблема. Хм .. – DanielRak

2

У меня была такая же проблема. Я пробовал исправления выше и другие, но ничего не получилось. Затем я наткнулся на https://github.com/MrAlek/AWPercentDrivenInteractiveTransition, который исправил все.

Как только вы добавите его в свой проект, просто замените UIPercentDrivenInteractiveTransition на AWPercentDrivenInteractiveTransition.

Кроме того, перед началом интерактивного перехода необходимо установить аниматор. В моем случае, я использую тот же класс для UIViewControllerAnimatedTransitioning и UIViewControllerInteractiveTransitioning, так что я просто сделал это в init():

init() { 
    super.init() 
    self.animator = self 
} 
Смежные вопросы