Drop me an email if you'd like to hire me (part time) or learn more about what I do. You can read about my experience and references on LinkedIn.
iOS: Custom View Controller Transition by expanding view
I was looking for inspirations on dribbble.com and found work
that shows nice transition between view controllers by expanding a view (e.g. a button) in
every direction. You can find it here: Login & Home Screen.
It is more like Android material design style animation, but I think it may
fit nicely in any onboarding process animations.
Let’s disassemble this animation.
There is a view that is a source of animation. Let’s call it expandable view.
In this work on dribbble the expandable view view is a “Sign in” button.
(I’ll simplify it and just use button that is ready to be scaled. You could use
additional delegate to notify the expandable view that it should prepare for
being expanded - It could also implement Expandable protocol or something similar)
When user taps the button, the first step is to change the appearance of the
expandable view. The view is about to scale to fill entire screen, so
everthing that would not look good is removed from the view. In this case this
is loading spinner and plus sign that is removed from the view. The only thing
that will be scaling is simple circle button with solid background.
The next step is the scaling process itself. The button expands so it fills
After view expanded quickly next view controller is presented by simple fade.
UIViewControllerAnimatedTransitioning - The protocol is used by animator,
the class that knows how the animation look like.
UIViewControllerTransitioningDelegate - The protocol is used by transitioning
delegate. It knows what is the total length of the animation and can instantiate
and return animators for both presenting and dismissing view controllers.
In this case I’ll only care about presenting animation.
At first, we have to create transitioning delegate that will return animators
for presenting and dismissing view controller (we care only about presenting now).
The init(expandableView:expandViewAnimationDuration:presentVCAnimationDuration:) takes
reference to view that will be expanded (button), and animation durations that
specifies how long expanding process is and how long is fade of destination
view controller after expandable view is fully expanded.
Two remaining methods are the one from UIViewControllerTransitioningDelegate.
First returns ExpandingViewTransitionAnimatorPresent animator which is used
to present new view controller.
Second method returns nil as we don’t care about dismissing animation.
Default dismiss animation will be used in this case.
The foundation of animator look like this.
The first thing is to calculate how much the expandable view should expand.
The idea is simple. We need to check how far the view is from the edges of the screen,
take the longest distance and use it to calculate scale that should be applied.
After we find such maximal offset, then we look for the biggest dimension of the
expandable view and for longest dimension of the source view controller
which should be full screen - I think we could use dimension of UIScreen.mainScreen().bounds too.
It might work even better for some cases.
With such informations we’re able to calculate new scale properly.
Here is how the transition code look like.
Using UITransitionContextFromViewControllerKey and UITransitionContextToViewControllerKey
keys, we can obtain source and destination view controllers via viewControllerForKey method.
Then as documentation says presentation style of destination view controller is set
to custom - destinationVC.modalPresentationStyle = .Custom.
Animator provides us containerView via transitionContext - see UIViewControllerContextTransitioning for details.
Source and destination view controllers are added to this container view.
We have to store somewhere begin state of zPosition and layer.transform of
expandable view so we can bring it back to the state before scaling.
After this there is just simple animation of a transform of expandable view
and after this finished, the destination view controller is presented.
After all of this is done and only destination view controller is on screen
we can bring previous appearance of the expandable view.
When everything is done you have to mark that the transition completed.