Making Custom Transitions Between UIViewControllers
I released a project called TRVSNavigationControllerTransition. The project adds convenient methods to translate the entire UINavigationController’s view while pushing and popping UIViewControllers to and from UINavigationControllers, rather than translating the viewController’s view — which is how UINavigationController’s pushViewController:animated: works.
Example
These images illustrate the difference. In the first image, the navigation controller translate’s the view controller’s view. The problem: if the view controller that’s pushed hides the navigation bar, then the navigation bar will suddenly and awkwardly hide during the push.
In the second image, using TRVSNavigationControllerTransition, the navigation controller translate’s the navigation controller’s view. So the navigation bar remains view until the animation’s finished.
How to make your own transition
TRVSNavigationControllerTransition works like this:
- Take a snapshot of the current view in the form of a CALayer and add it as a sublayer of the current view.
- Push or pop the next view without animation.
- Take a snapshot of the new view in the form of a CALayer.
- Add whatever animations you want to those layers for their transition.
- Remove the layers from their superlayer once the transition animation finishes.
See UINavigationController+TRVSNavigationControllerTransition.m for more details.
Rejected Alternative
I saw others using a CATransition, like so:
CATransition* animation = [CATransition animation];
animation.duration = 0.3f;
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromRight;
The problem is that kCATransitionPush’s animation looks different from UINavigationController’s pushViewController:animated:. It doesn’t fit.
Install
Grab the project at GitHub
repo, or
with the CocoaPod spec using the name: TRVSNavigationControllerTransition
.
Use
To use TRVSNavigationControllerTransition, link your binary with the QuartzCore.framework library. Then in your code write:
[self.navigationController pushViewControllerWithNavigationControllerTransition:viewController];
[self.navigationController popViewControllerWithNavigationControllerTransition];