Synchronously Animating Toolbar, TabLayout, FloatingActionButton and StatusBar Background Colors on Android
Recently I came across a situation where I wanted to animate the background color of the app’s Toolbar, TabLayout, FloatingActionButton, and the window StatusBar when the selected tab changes.
Here’s a look at the expected result:
Basically within the onTabSelected method of my TabLayout.OnTabSelectedListener implementation, I wanted to animate from the current color to the new tab’s corresponding color, ensuring that all views are animating simultaneously.
To do this, I chose to use the ValueAnimator which allows you to iterate over the difference of two values over a timed interval. I also used an ArgbEvaluator for the ValueAnimator’s evaluator to handle the calculation of each animation step between the two ARGB colors.
Here’s what that looks like:
int colorFrom = ((ColorDrawable) toolbar.getBackground()).getColor(); int colorTo = getColorForTab(selectedTab.getPosition); ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
An important note here, it’s critical that you use the actual color value, not the color resource IDs!
We use the toolbar’s current background color as the starting color of the animation, and determine the color to animate to based on the newly selected tab.
Now the ValueAnimator can be used to inform us of what color to use during each animation iteration:
colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animator) { int color = (int) animator.getAnimatedValue(); toolbar.setBackgroundColor(color); tabLayout.setBackgroundColor(color); floatingActionButton.setBackgroundTintList(ColorStateList.valueOf(color)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { getWindow().setStatusBarColor(color); } } }); colorAnimation.start();
Before calling start, we add an AnimatorUpdateListener that will be called with the animated value during each iteration of the animation. We take the animated value, cast it to an int in order to represent the actual color, and set it on the views.
The Toolbar and TabLayout are simple enough, we just call the standard View method setBackgroundColor with the animated value.
The FloatingActionButton provides a minor annoyance because it overrides and doesn’t implement the setBackgroundColor method, so we can’t use that. Instead we use setBackgroundTintList with a single value: our animated color.
Finally, setting the StatusBar color is only supported on SDK version 21 and up, so we do a quick check first on the device’s SDK version prior to calling setStatusBarColor on the Window, again with the animated color value.
Finally, the ValueAnimator is a subclass of Animation so we can do some standard animation things like setting the duration:
... colorAnimation.setDuration(250); ... colorAnimation.start();
And that’s all there is to it - the animation is a pretty nice touch in my mind, and definitely worth the minimal effort it takes to implement.