For a while now we’ve had real time blur built into iOS in the form of UIVisualEffectView and with iOS 8 Apple introduced UIModalPresentationOverCurrentContext, allowing view controllers to be presented modally without the presenting controllers view being removed from the view hierarchy. This allowed combining both blur and view controller presentations creating the effect used by Apple since iOS 7 within some of the stock apps.
Achieving this effect using the view controller transitioning api’s introduced in iOS 7 is relatively straight forward. However what if you want the same effect using a UINavigationController push/pop transition? I’m going to show a way in which this can be achieved.
We‘ll be using the normal UIViewControllerTransitioningDelegate methods to specify the animation. Firstly we’ll create an ‘animator’ object which will mimic the standard UINavigationController slide animation.
To implement the slide animation we’ll get the to and from views and position them accordingly as well as adding out to view to the container as per Apples guidelines.
We’ll then animate using a spring animation to more closely reflect the default UINavigationController slide.
Once our animator is finished we can hook this up within our presenting view controller. First we’ll conform to the UIViewControllerTransitioningDelegate and since this will be a UINavigationController transition we’ll also need to conform to the UINavigationControllerDelegate. We only need to implement a single method from this protocol in order to use our custom animator object.
The pushPopAnimatorForPresentation: method simply returns our custom animator object after setting the presenting property accordingly.
This is all we need to mimic the default slide animation of UINavigationController however since the presenting view controller is removed by default for a navigation controller transition, even when UIModalPresentationOverCurrentContext is used, the effect isn’t quite what we were after.
As you can see the from view is removed once the animation completes. To workaround this we can add the view back into the hierarchy after letting UIKit know the animation has completed within the completion block.
With just a small amount of additional effort we can also mimic the default interactive edge swipe gesture by adding a UIPanGestureRecogniser to the navigation controllers view and implementing an additional method from the UIViewControllerTransitioningDelegate protocol. The boilerplate code for handling the pan can be seen in example project.
For the interactive transition we will also have to handle the case whereby the dismissal is cancelled by the user.
Perhaps useful to know that this animation reusable with traditional modal presenations outside of a UINavigationController.