While working on one of my side projects, I wanted the app I was working on to have one background view, that’s visible in all viewcontrollers and while transitioning between them.
My first idea was to add the background view to the app’s main window and make each viewcontroller’s view transparent. That didn’t really work out as expected, because transparent views seem to make the
UINavigationController’s default transitions glitch out.
But it’s actually pretty close to what I wanted to achieve, so (after some other failing attempts) I tried coming up with a custom transition to see whether the views would still glitch out. Turns out they don’t! With a custom transition, the result looks fine.
The transition itself is actually pretty easy and straight-forward:
1: In the transition’s
init method, the start and end frames for the views participating in this transition are calculated. The calculation incorporates the
UINavigationController’s transition operation (e.g. push or pop) and is done using a simple helper-struct.
2: In this method, the transition is layed out and performed. At first we grab both viewcontrollers and check whether the
containerView was created.
containerView acts as the superview for the views involved in the transition and must be used as the container for all other views involved in the transition. Thus we add both our viewcontroller’s views to it.
4: These lines are needed to make Auto Layout happy. If you don't include these lines, there's a good chance your UI elements will be lay out wrongly after the transition.
5: Here, the sliding animation is prepared. The
toViewController should be sliding in from the left (pop) or right (push) side of the screen, so it needs to be positioned just outside the screen’s bounds right before the animation kicks in.
6: This is where the transition is performed. All we need to do to achieve the sliding effect is setting the frames the viewcontrollers should have at the end of the transition. In the completion block, we need to tell the
transitionContext that the transition was actually completed.
Next, we need to connect our custom transition with an
UINavigationController instance. I did this in my
1: Create an instance of
NavigationControllerDelegate (defined below).
2: Create an instance of a standard
UINavigationController instance and set the delegate.
3: In the delegate method for the transition to be used within the navigation controller, simply return the custom transition.
That’s it! The custom transition is set up and ready for use. In my case, I also added a custom background view to the window and set the viewcontroller’s background colors to clear.
I published the full source code of a working example for an app with one background view, transparent viewcontrollers and not-glitched-out transitions on Github: AppWideBackgroundExample.