I want to implement an interactive transition between two view controllers. I would like it to be a modal or present transition.
- I want the app to start out on the first view controller and allow the user to swipe down to bring in the second view controller
- The second view controller should come in and cover the current (first view controller) rather than move it out of the way
I understand that I would need to use the following.
transitioningDelegate
animationController(forPresented:presenting:Source:)
interactionControllerForPresentation(Using:)
UIPercentDrivenInteractiveTransition
I am having trouble figuring out how to implement all this. I can't seem to find anything useful or any working examples in swift 3. For now I created a simple single view application with two view controllers VC1 (blue background) and VC2 (yellow background) to easily test out any possible solutions.
See WWDC 2013 video Custom Transitions Using View Controllers for discussion of the transition delegate, animation controller, and interaction controller. See WWDC 2014 videos View Controller Advancements in iOS 8 and A Look Inside Presentation Controllers for introduction to presentation controllers (which you should also use).
The basic idea is to create a transition delegate object that identifies what animation controller, interaction controller, and presentation controller will be used for the custom transition:
You then just have to specify that a custom transition is being used and what transitioning delegate should be used. You can do that when you instantiate the destination view controller, or you can specify that as part of the
init
for the destination view controller, such as:The animation controller specifies the details of the animation (how to animate, duration to be used for non-interactive transitions, etc.):
The above animation controller handles both presenting and dismissing, but if that feels too complicated, you theoretically could split it into two classes, one for presenting and another for dismissing. But I don't like to have two different classes so tightly coupled, so I'll bear the cost of the slight complexity of
animateTransition
in order to make sure it's all nicely encapsulated in one class.Anyway, the next object we want is the presentation controller. In this case, the presentation controller tells us to remove the originating view controller's view from the view hierarchy. (We do this, in this case, because the scene you're transitioning to happens to occupy the whole screen, so there's no need to keep the old view in the view hierarchy.) If you were adding any other additional chrome (e.g. adding dimming/blurring views, etc.), that would belong in the presentation controller.
Anyways, in this case, the presentation controller is quite simple:
Finally, you presumably want an gesture recognizer that:
UIPercentDrivenInteractiveTransition
;UIPercentDrivenInteractiveTransition
as the gesture progresses;UIPercentDrivenInteractiveTransition
when it's done (to make sure it's not lingering about so it doesn't interfere with any non-interactive transitions you might want to do later ... this is a subtle little point that's easy to overlook).So the "presenting" view controller might have a gesture recognizer that might do something like:
You'd probably also want to change this so it only recognizes downward gestures (rather than any, old pan), but hopefully this illustrates the idea.
And you presumably want the "presented" view controller to have a gesture recognizer for dismissing the scene:
See https://github.com/robertmryan/SwiftCustomTransitions for a demonstration of the above code.
It looks like:
But, bottom line, custom transitions are a little complicated, so I again refer you to those original videos. Make sure you watch them in some detail before posting any further questions. Most of your questions will likely be answered in those videos.