Proper way to implement a custom UIViewController interactive transition using UIViewControllerInteractiveTransitioning Delegate Protocol
Asked Answered
F

2

47

I'm interested in a concise example of how to create an NSObject subclass that implements the UIViewControllerInteractiveTransitioning protocol to manage a custom interactive transition between two UIViewControllers. Ideally in response to a swipe gesture. Something akin to the iOS7 default interactive swipe that now comes with UINavigationController, but a custom/manual implementation example of this.

I've read the docs:

And looked at a few examples elsewhere:

  • one
  • two
  • three
  • four (I set this up but it's more about UIViewController containment and manual implementation of these transitions rather than UIViewControllerInteractiveTransitioning

The docs are fairly clear but dont reference sample code. And the examples leave a little to be desired (unanswered questions about how the various pieces are tied together).

So my questions are:

  1. Can someone help fill in the blanks about how to tie a gesture (e.g. a swipe) to the object that implements the UIViewControllerInteractiveTransitioning protocol?
  2. What is the relationship between object implementing the UIViewControllerInteractiveTransitioning protocol and that implementing the UIViewControllerAnimatedTransitioning protocol? Seems like you must have both to trigger interactive transitions...

Thanks in advance...

Fuqua answered 23/9, 2013 at 20:51 Comment(5)
I just saw an iOS7 sample app with different custom transitions, maybe you can use that for inspiration: github.com/shu223/iOS7-Sampler/blob/master/iOS7Sampler/…Turquoise
Check out this post: scottlogic.com/blog/2013/09/26/… And the associated code: github.com/ColinEberhardt/VCTransitionsLibraryBurro
Your sample code is closed/couldn't be found.Sergo
Thanks for the heads up, sorry about that, I just took it down a couple days agoFuqua
Repo is back up, or never was down, can't remember what happened, maybe I had changed the repo's name or something. Anyway it's there now.Fuqua
C
13

1) The easiest way to tie a gesture to the UIViewControllerInteractiveTransitioning object, is making it subclass of UIPercentDrivenInteractiveTransition. Then where you implement the gesture handler, you call updateInteractiveTransition: here an example with code:

-(void)handlePinch:(UIPinchGestureRecognizer *)pinch {

    CGFloat scale = pinch.scale;
    switch (pinch.state) {
      case UIGestureRecognizerStateBegan: {
          _startScale = scale;
          self.interactive = YES;
          [self.navigationController popViewControllerAnimated:YES];
          break;
      }
      case UIGestureRecognizerStateChanged: {
          CGFloat percent = (1.0 - scale/_startScale);
          [self updateInteractiveTransition:(percent < 0.0) ? 0.0 : percent];
          break;
      }
      case UIGestureRecognizerStateEnded: {
          CGFloat percent = (1.0 - scale/_startScale);
          BOOL cancelled = ([pinch velocity] < 5.0 && percent <= 0.3);
          if (cancelled) [self cancelInteractiveTransition];
          else [self finishInteractiveTransition];
          break;
      }
      case UIGestureRecognizerStateCancelled: {
          CGFloat percent = (1.0 - scale/_startScale);
          BOOL cancelled = ([pinch velocity] < 5.0 && percent <= 0.3);
          if (cancelled) [self cancelInteractiveTransition];
          else [self finishInteractiveTransition];
          break;
      }
    }
}

This code is from https://www.captechconsulting.com/blogs/ios-7-tutorial-series-custom-navigation-transitions--more

2) The function animateTransition of UIViewControllerAnimatedTransitioning is used to perform the interactive transition. It is automatically partitioned in "keyframes" thanks to your previous call to updateInteractiveTransition. But I suppose that if you implement your startInteractiveTransition: method of UIViewControllerInteractiveTransitioning (so without using UIPercentDrivenInteractiveTransition subclass) then you are responsible to manage the fully transition (not sure about that.. sorry but the documentation in my opinion is not really clear).

Constantin answered 11/1, 2014 at 23:20 Comment(1)
If you implement startInteractiveTransition: method the animateTransition is never called (debugging it for hours, thanks for the idea)Fanchon
M
7

Apple does indeed provide an example project now for how you can achieve this. Having said that, I don't think it's the finest/clearest example, but it should get you on the correct path.

They also have a WWDC video that takes you through this very project.

Be warned that it's a fairly complex example, but if you do manage to break it apart and understand the various pieces, you should be equipped to deal with more or less anything on the transition front.

Essentially, the project splits the problem into two helper classes, 1) an AssetTransitionController that is initialised with, and exists for the life of, the view controller, and 2) an AssetTransitionDriver object that is created at the beginning of, and exists for the duration of, a transition.

The AssetTransitionController is fairly simple, it conforms to UIViewControllerAnimatedTransitioning and UIViewControllerInteractiveTransitioning managing the lifecycle of the AssetTransitionDriver.

The AssetTransitionDriver is a simple NSObject sub-class but actually ends up far more complex. It manages the main UIViewPropertyAnimator, creating the view hierarchy for the transition, and responds to the interaction driver (a pan gesture recogniser). It also vends its animator to the AssetTransitionController when requested.

It doesn't use UIPercentDrivenInteractiveTransition at all.

Macmullin answered 8/8, 2018 at 17:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.