Note: iOS 7 has awesome APIs that make this sort of thing a lot funner, easier and powerful. When the SDK’s NDA is over I’ll be releasing some open source code and blog posts about them.
I just released a project called TRVSNavigationControllerTransition that adds convenience methods to UINavigationControllers to push/pop UIViewControllers that translate the entire UINavigationController’s view rather than its viewController’s view (which is how UINavigationController’s pushViewController:animated: behaves).
In the top example of the images below, only the view controller’s view is translated so if the pushed view controller hide’s the navigation bar then the navigation bar in the current view will suddenly disappear. In the bottom example using TRVSNavigationControllerTransition, the whole navigation controller’s view is translated in, and the navigation bar remains correctly in the current view until the animation completes.
Development and alternatives
Before, I tried and 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 not only animates the translations like you’d expect, but also the opacities of the views so the transition looks differently from UINavigationController’s pushViewController:animated:.
The basic idea on how to make your own is pretty simple though,
- take a snapshot of the current view in the form of a CALayer and add it as a sublayer of the current view
- push/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 to form their transition
- remove the layers from their superlayer once the transition animation is complete
See UINavigationController+TRVSNavigationControllerTransition.m for more details.
To use TRVSNavigationControllerTransition just make sure your binary is linked with the QuartzCore.framework library, and then to use:
# to push, called just as you would with pushviewcontroller:animated: [self.navigationController pushViewControllerWithNavigationControllerTransition:viewController]; # to pop called just as you would with popviewcontrolleranimated: [self.navigationController popViewControllerWithNavigationControllerTransition];