This post will show how to implement a transition where one item from “screen 1” flies into “screen 2”. More specific: we want to move an UIView from one UIViewController to another.
There are a some good introductions to UIViewController transitions, but I couldn’t find anything that fit my wants exacty, so I’m writing this post to fill the gap. Admittedly, I didn’t do a lot of research, as I planned to implement the transition myself.
Here is the end result of what we will be making. As you see, the profile pictures of the list animates nicely (well..) into the second screen, the detail view.
You might notice that the dismissal animation is not nice, the reason for this is to keep the examples focused. To have a nice dismiss, we need to add some code to essentially run the animation in reverse.
That might come in another article.
So what is exactly happening here? Is the view actually transferred from one UIViewController to another UIViewController? No, it is not. It is all smoke and mirrors.
What really happens is that we create a fake profile picture, identical to the one in the list, that we add to a special view within the transition context. We then move that fake view into the position of where it should be in the second view. At the very last moment, we remove the fake view to reveal the identical view in the second view controller. The users should be none the wiser.
Here’s an approximation of how it looks when you tap a row in the table view.
Once we tap the row, we are given a sort of temporary space to add our views to. Here we have copied the UIImageView with the profile picture and added it to that space. Then we have retreived the intended frame in the second screen.
Not pictured is the actual animation we kick off.
So let’s see how this all works then. You might want to look at the introduction tutorial at ray wenderlich’s website, as it goes into more details of each step, why it is done.
My assumption with this code is that you are kind of familar with the idea of transitions, maybe have implemented it from the tutorial linked above but didn’t find exactly what you wanted - just like me. So the code will show kind of the setup, but mainly the meat - getting that profile picture into the second view controller.
The parts we will touch are
- ListViewController - The 1st screen, the initiator
- DetailViewContrller - The 2nd screen, the target
- ListToDetailAnimator - A class that will coordinate/start the animation, keep track of from/to where the animations will take place
ListViewController - Screen 1
So the very basic setup is something like this. We give our ListViewController the ListToDetailAnimator object.
We then make it conform to the
UIViewControllerTransitioningDelegate protocol, so that the app (?) knows that the VC is able to take care of the transitions from it. The method itself just returns the transition to the system, it doesn’t deal with the transitions like animations itself.
DetailViewController - Screen 2
The second screen only needs some way for the animator object to know the location of the profile picture, so that it can get the frame. For that, I just made the UIImageView public.
ListToDetailAnimator - Basic overview
Now we get to the actial meat of the solution. This class is that literally makes the profile picture move “between” the screens.
For this class, let’s start with the base minimum and some explanations, then I will add the profile picture movement.
This should be fairly readable as it is. We can see that the
transitionContext gives us access to the source VC and the destination VC. Here we add the destination into the context with alpha 0. This let’s us then animate it in with the normal UIView animation methods.
At the end, we tell the context that we’re done.
Something to note here is that the source VC’s view is automatically added into the context, so we could move it around if we wanted to. It is also automatically removed once we finish the transition. Again, the ray wenderlich link talks a bit more about this.
So that was the most simple thing we could do, fading it in. Now let’s see how we can get the profile picture animated.
ListToDetailAnimator - Actually moving the UIImageView
All of this code lives in the
animateTransition method you saw above.
Again the code should be fairly self explanatory here. But some parts may be less obvious.
For example, in step 1. and 6. we hide the header view inside the destination view controller, but why? This is to make sure that we don’t see the header being already in the view during the animation. The whole point if this animation is to make it look like the picture is being transferred into the new screen, if it is there already the illusion is broken.
This is actually done in the ListViewController as well. When we tap the row, we hide the small UIImageView in the UITableViewCell. Again this is to make it look like it is moving into the next screen.
Speaking of starting the animation..
ListViewController - Setting up the transition
There are a few more key parts that I haven’t touched on yet. The transition object needs some data injected to work properly. For example, it needs the image to add into the fake UIImageView, as well as a location to start from.
Again this is fairly straight forward to read.