Toolbar, TabLayout, FloatingActionButton以及状态栏的同步变色
最近我遇到一个情形,当tab选中项改变的时候,以渐变动画的方式改变Toolbar,TabLayout,FloatingActionButton以及StatusBar的背景颜色。
这里是我期望的结果:
我的基本想法就是在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();
这就是实现这个效果的所有东西了。我个人觉得这个效果看起来不错,值得为之花上一点时间。