The latest version of Apple’s mobile operating system brought to us a new, unified way to implement custom transitions between view controllers. Before iOS 7 custom transitions were possible but a little painful. Making them interactive, was even harder. Apple’s transitioning API made our life easier and here is why.
A sample project can be found at the end of the article.
Basics
Transitioning API strongly relies on protocols (delegates precisely). The main protocol we are interested in is UIViewControllerAnimatedTransitioning
. There are two obligatory methods to implement:
- (NSTimeInterval)transitionDuration:(id )transitionContext
should return the whole transition duration and second- (void)animateTransition:(id )transitionContext
should implement all the animations
Pretty simple, isn’t it?
Now let's say we would like to use our transition animation to present the view controller. The source view controller should conform to UIViewControllerTransitioningDelegate
protocol. We are especially interested in two methods:
- (id) animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
- (id) animationControllerForDismissedController:(UIViewController *)dismissed
Both methods should return an object that conforms to UIViewControllerAnimatedTransitioning
. The object returned by the first method will be responsible for presenting our controller and the object returned by the second method for dismissing it.
There’s one more little thing to do. Before we present our controller we need to set modalPresentationStyle
property to UIModalPresentationCustom
and transitioningDelegate
property to self
. This can be done in -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
for instance.
So far we discussed custom transition for presenting the view controller. What about push-and-pop transitions? There is an appropriate method to do this as well! This method is a part of UINavigationControllerDelegate
protocol and it is:
The UINavigationControllerOperation
tells us whether we have to deal with pop or push transition. Knowing the type of transition we can easily provide corresponding animations. That’s all.
Interactive transitioning
Since we are on the navigation controller we will turn its transitions to become interactive.
To achieve that we will need an UIScreenEdgePanGestureRecognizer
added to pushed controller’s view. For this controller, we also need two additional properties:
The UIPrecentDrivenInteractiveTransition
object allows us to control our transition by providing its progress. You will see how this is done in code. The interactive
property indicates if the user began using gestures or just tapped the back button.
A gesture recognizer can be added like this:
The - (IBAction)handlePopGesture:
method looks like this:
As you can see each action being invoked progress
is calculated and, according to the gesture state, the transition is updated, cancelled or finished.
More attentive readers will notice that self.interactivePopTransitionController
was not initialized yet. This is done in one additional method of UINavigationControllerDelegate
All we need to do is to check if the transition should be interactive and if this is a pop transition and then return UIPrecentDrivenInteractiveTransition
object. Otherwise, nil
can be returned.
Believe it or not but we are done here!
Summary
Implementation of custom interactive transitions in your app can add some nice feelings and experiences. The new transitioning API can be confusing at first, but after a while, it appears to be a flexible solution, where the only limitation is our imagination.
A sample project can be downloaded from Github. Check it out and let us know what you think.