Circular reveal animation between Fragments
TL;DR: In this article we are going to talk about a newly implemented feature for Prezi Next users in the Prezi Viewer app, where we implemented a not-so-obvious circular reveal animation. Although it’s easy to implement the basics, it still can be hard to do it right. As always,
the devil is in the details
The feature is about sharing prezis. Basically you can create multiple unique share links for a prezi, and later you can edit, share again, or deactivate the link. If you deactivate a link, the users won’t be able to open the prezi again from that particular link. With Prezi Analytics you can even track the link. The screens are the following:
The FloatingActionButton screams for a circular reveal animation, but before we go further, lets think about the logic behind the feature first. It’s worth mentioning that we use MVP in our app whenever it makes sense.
Our feature creation process starts with a brainstorming session where we come up with a simple, but perfectly enough solution for our case. We create a new Activity with an ActionBar. There are two Fragments, one for the list with the FloatingActionButton, and one with the create/edit screen. We think the edit, and create screens similar enough to use one Fragment, and based on a boolean value (passed through as an argument) we decide which one we show. For the two Fragments (these Fragments are the Views) we have two Presenters, and one Model. The Model is responsible for keeping the data in a persistent place, and calling the listeners if something happened with the link’s list (create, update, delete). One Presenter handles the list screen, and the FloatingActionButton click, the other one handles the edit/create part. The Activity changes the ActionBar’s states (change the title and the icons) when it’s required from the Presenters. At the end we have two Fragments as Views, and two Presenters for them, one Model for keeping the data safe and an Activity which holds them together:
Circular reveal animation
Circular reveal is very easy to implement. A couple of lines of code and ta da!, it works, and it’s awesome. We implement it in a helper class, since these animation codes really make the beautiful, simple Fragment classes ugly. We also create a background color animation to make the circular reveal even smoother. It’ll change from (prezi) blue to white during the reveal. (With the white background it’s not really visible that the circular reveal is happening.)
From the Fragment’s side it’s really easy to use. We start the animation inside the onLayoutChanged callback in the destination Fragment, so we have to pass the positions through the arguments from the list Fragment. We need the center of the FloatingActionButton, and the size of the Fragment’s root view (to calculate the radius of the reveal animation).
It’s clean and nice, because we only have to add 1 line to the DetailFragment, and we don’t have to check the android version there. If it’s an “older” (<21) device, it’s just won’t add the listener, so no problem at all.
Let’s have a look at the result:
The list Fragment disappears before the circular reveal animation could finish. It would be nice if it would stay in place during the animation, but this is not going to happen with the current workflow. We replace the Fragments, so the Android has no intention to “keep it there for a while” for us, and we are not able to ask it to do so. An easy solution is to put those two Fragment on top of each other, and run the reveal only on the top container, and the list will be there all the time. We chose this because in our simple case it’s enough (if we had more Fragments we would definitely use some other technique).
Circular exit animation
We also add a circular exit animation to the AnimationUtils class.
For the exit animation we have to use a little trick. Since the two Fragments are on top of each other, we have to remove the top DetailFragment when the exit animation is finished. We create a Dismissible interface, which is responsible for a dismiss event (in our case the dismiss event is the exit animation), and then call the OnDismissedListener when it’s done. In our case the DetailFragment implements Dismissible, and do the following in the dismiss method:
With the Fragment “stack”, and circular exit animation it looks much better:
Smoke and mirrors
It’s already much better than the first version, but I cannot go to sleep when the FloatingActionButton looks like this during the animation:
It would be better if the plus sign stays there during the animation, and the color change (to white, and to blue) will hide/show it automagically.
We can do it multiple ways (as always). We can add this plus sign to the Activity and show/hide it from the Fragment, or add it only to the DetailFragment and add a bit more logic there (hide it when the reveal animation finished, and show if dismiss starts). I prefer the second solution, because the Activity should not know about these tricks.
Lets check out our final, little bit refactored version of AnimationUtils.
Now we can sit back and enjoy our beautiful animation:
Why spend time on details?
Very good question. Since we spent quite a lot of time on a simple reveal animation it’s worth mentioning why we are doing this. These smoke and mirrors can be very helpful in several ways. I would like to mention only two, what I personally think are the most important.
You reserve time for the app to do something important during the animation. Your app will look faster.
The default medium animation duration is 300 ms. We can use that time for example a network call. With good network connection 300 ms is more than enough for a network call, so when the screen is ready the user already see the result of the call. The user will think the app is faster (faster than you show the screen instantly and show a loading indicator).
Users are more forgiving with a smoothly working app.
There is no such thing as a bug free app. If the user runs into a problem (God forbid, a crash) they tend to forgive you, if the app works smoothly otherwise.
The circular reveal and exit animation is very easy to implement, but sometimes you have to consider a lot of things when you want to implement it properly. In our case we changed the Activity’s structure, and added more logic here and there, just to make the animation smoother/better.