Implementing Complex Animations in Android (Full Working Code)
Android has excellent support for animations but sometimes you see something like this:
and get stuck and wonder where to begin. In this post I will try to accomplish this beautiful animation and go through each step.
There is lot going on when you see it at first but we can break it down to three major animations.
1. The animation that plays when user taps on the card:
2. The animation of launching another screen with details:
3. Scroll up animation which shrinks icons to dot indicators:
I will try to implement 2nd and 3rd, 1st one is easy and is left as an exercise for developers.
Remember Shared Element Transitions were added in Android 5.0 (API level 21)? You just tell the OS about the views that are shared between current and next screen (
Fragment) and OS will take care of doing a smooth transition of those views from old state to new state which can involve translation, rotation, scale and visibility etc. It can even do matrics animation on
We will utilize Shared Element Transitions in our first animation. We have a
RecyclerView that shows circular images. On tap of any of those, we want to animate all the visible items to correct place on the next screen. For that we will have to ask
LayoutManager for visible item positions:
Once we have visible positions, just get the
itemView associated with positions and start the next activity with those views as shared elements:
On the next activity, all you need to do is assign that
unique_key_x to some views and OS will take care of this animation. We are using
IconPageIndicator which shows corresponding icons as indicators for
ViewPager so we set same transition name for same position in
view.setTransitionName(“unique_key_” + i);
and voila! we are already done with first part of animation.
Second part of animation that we are trying is fairly complex. There is lot going on when you scroll the list. Icons shrink to dots as you scroll up and when you scroll down, dots expand to icons. Another interesting thing is that this indicator stays centered vertically at all times in
First thing first, we want our
IconPageIndicator to stay centered vertically when our
Toolbar expands or collapse (of course we are using
CoordinatorLayout, as documentation puts it, is a super powered
FrameLayout. Each child in
CoordinatorLayout can listen for interesting events happening to other childs via
CoordinatorLayout.Behavior and can respond accordingly. We will use that to our advantage to stay centered vertically inside
First we let our
Behavior know that we are interested in
and then whenever
onDependentViewChanged() is called, we do our magic while respecting
This will keep the indicators centered. Now we have to shrink icons to dots when user scrolls BUT if you were paying attention, there is another thing going on here; Dots are centered horizontally but icon indicators start from middle and scroll horizontally when you scroll
ViewPager. That means we need to center indicators when shrinking to dot.
Let’s divide and conquer here. We will add the start and end padding in indicators so that it starts showing from middle. We do this in
OnPreDrawListener because we can only do it once views are measured:
Now, let’s move onto shrinking part. Remember we overrode
onDependentViewChanged()method in our
Behavior. This method will get called everytime there is a change in
CollapsingToolbarLayout. We can get total scroll range and current scroll, which are the only two things required to tie our animation with scroll:
collapse() we can do our trickery of scaling down the icons to dots. Be careful though not to shrink icons to oblivion, dividing by 1.2 worked fine for me:
We also want our icons to become gray indicators on scroll up so for that:
At this point our app has almost everything it needs to look like the one we saw in gif. Except there is still room for improvement! Notice that dots are just perfectly centered horizontally. We want to achieve that smoothly during up and down scroll. If we denote current collapse percent with
p, center of indicators as
c, current selected expanded icon position as
s and scroll along x-axis as
sx then we can write this relation down as an equation:
sx = (p x c) + ((1 - p) x s
Which basically means that when
p changes from 0 to 1, we change the scroll in a way that it either gives full weight to center position
c or current selected position
s, at peak values. In code it looks even uglier:
And when you hit run you see this!
Mastering ViewPager with Directed Acyclic Graph
Ever thought of using Directed Acyclic Graph (DAG) with ViewPager? Its a perfect combination.
Full source code:
AnimationsPlayground - This repo is an attempt to answer the question asked here http://stackoverflow.com/questions…
Motivation behind this post: https://stackoverflow.com/q/43542302/826606
If you have a better way to implement this animation, shoot it out in the comments or create a pull request. Feel free to ask any question and suggest topics which you think I should write on in the future.