Toolbar, TabLayout, FloatingActionButton以及状态栏的同步变色

原文:Synchronously Animating Toolbar, TabLayout, FloatingActionButton and StatusBar Background Colors on Android 

最近我遇到一个情形,当tab选中项改变的时候,以渐变动画的方式改变Toolbar,TabLayout,FloatingActionButton以及StatusBar的背景颜色。

这里是我期望的结果:

android-animate-toolbar-color-1.gif

我的基本想法就是在TabLayout.OnTabSelectedListener的onTabSelected方法中,让当前颜色动画过渡到新tab所对应的颜色,同时确保动画是渐进的。

为此,我使用ValueAnimator,它可以让你在一段时间内遍历两个值之间的区别。我还使用了ArgbEvaluator作为ValueAnimator的估值器,用来处理动画中每一步对两个ARGB颜色值所做的计算。

这里是代码:

int colorFrom = ((ColorDrawable) toolbar.getBackground()).getColor();
int colorTo = getColorForTab(selectedTab.getPosition);
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);

这里要注意一点,你必须使用颜色的实际值,而不是颜色的资源ID!

我们把toolbar的当前背景颜色作为动画的起始颜色,而要过渡到的颜色是基于新选中的tab项。

现在可以用ValueAnimator来告诉我们动画过程中每一步是什么颜色:

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();

在调用start之前,我们添加了一个AnimatorUpdateListener,,它会在动画期间被不断的调用,我们可以获取到此时颜色按照动画变化后的值,把它转换成int,然后在View上设置这个颜色。

Toolbar和TabLayout比较简单,我们只需调用View的setBackgroundColor方法。

FloatingActionButton可能要稍微麻烦点,因为它没有setBackgroundColor方法,因此我们无法使用。不过我们可以使用setBackgroundTintList方法。

最后,因为StatusBar颜色只在SDK version 21及以上才被支持,所以我们首先在调用Window的setStatusBarColor之前检查设备的SDK 版本。

ValueAnimator是Animation的子类,因此我们可以做标准动画的一些事情,比如设置持续时间:

colorAnimation.setDuration(250);
 
...
colorAnimation.start();

这就是实现这个效果的所有东西了。我个人觉得这个效果看起来不错,值得为之花上一点时间。