在Android上animation改变视图背景颜色

你如何animationAndroid上的一个视图的背景颜色的变化?

例如:

我有一个红色背景颜色的视图。 视图的背景颜色变成蓝色。 我怎样才能平滑过渡的颜色?

如果这不能与意见,可以select一个替代scheme。

我最终找出了一个(相当不错的)这个问题的解决scheme!

您可以使用TransitionDrawable来完成此操作。 例如,在可绘制文件夹中的XML文件中,您可以编写如下所示的内容:

<?xml version="1.0" encoding="UTF-8"?> <transition xmlns:android="http://schemas.android.com/apk/res/android"> <!-- The drawables used here can be solid colors, gradients, shapes, images, etc. --> <item android:drawable="@drawable/original_state" /> <item android:drawable="@drawable/new_state" /> </transition> 

然后,在你的实际视图的XML中,你可以在android:background属性中引用这个TransitionDrawable。

在这一点上,您可以通过执行以下命令来启动代码中的转换:

 TransitionDrawable transition = (TransitionDrawable) viewObj.getBackground(); transition.startTransition(transitionTime); 

或者通过调用:

 transition.reverseTransition(transitionTime); 

请参阅Roman的答案,以解决使用Property Animation API的另一个解决scheme,该答案在最初发布时不可用。

您可以使用新的Property Animation Api进行彩色animation:

 int colorFrom = getResources().getColor(R.color.red); int colorTo = getResources().getColor(R.color.blue); ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); colorAnimation.setDuration(250); // milliseconds colorAnimation.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animator) { textView.setBackgroundColor((int) animator.getAnimatedValue()); } }); colorAnimation.start(); 

为了向后兼容Android 2.x,请使用Jake Wharton的Nine Old Androids库 。

getColor方法在Android M中已被弃用,所以你有两个select:

  • 如果您使用支持库,则需要将getColor调用replace为:

     ContextCompat.getColor(this, R.color.red); 
  • 如果您不使用支持库,则需要将getColor调用replace为:

     getColor(R.color.red); 

根据视图如何获得背景颜色以及如何获得目标颜色,有几种不同的方法可以实现此目的。

前两个使用Android Property Animation框架。

在以下情况下使用对象animation器 :

  • 您的视图将其背景颜色定义为xml文件中的argb值。
  • 您的视图以前的颜色由view.setBackgroundColor()
  • 你的视图的背景颜色定义在一个drawable中, 不会定义任何额外的属性,如笔画或angular半径。
  • 您的视图的背景颜色定义在一个可绘制的,你想删除任何额外的属性,如笔画或angular半径,请记住,删除额外的属性不会animation。

对象animationview.setBackgroundColor通过调用view.setBackgroundColor来替代已定义的可绘制对象,除非它是ColorDrawable一个实例,它很less。 这意味着任何额外的背景属性从一个可绘制的笔画或angular落将被删除。

使用价值animation师,如果:

  • 您的视图的背景颜色在drawable中定义,还可以设置像stroke或corner radius这样的属性,并且您希望将其更改为在运行时决定的新颜色。

如果符合以下条件,请使用Transition可绘制的

  • 您的视图应该在部署之前定义的两个drawable之间切换。

当我打开一个DrawerLayout,我无法解决这个问题的时候,我遇到了Transition drawable的一些性能问题,所以如果遇到任何意想不到的结果,你可能会遇到同样的问题。

如果要使用StateLists drawable或LayerLists drawable ,则必须修改Value Animator示例,否则会在final GradientDrawable background = (GradientDrawable) view.getBackground(); 线。

对象animation师 :

查看定义:

 <View android:background="#FFFF0000" android:layout_width="50dp" android:layout_height="50dp"/> 

像这样创build和使用ObjectAnimator

 final ObjectAnimator backgroundColorAnimator = ObjectAnimator.ofObject(view, "backgroundColor", new ArgbEvaluator(), 0xFFFFFFFF, 0xff78c5f9); backgroundColorAnimator.setDuration(300); backgroundColorAnimator.start(); 

你也可以使用AnimatorInflater从xml中加载animation定义,如XMight在Android中的objectAnimator animate backgroundColor of Layout

价值animation师 :

查看定义:

 <View android:background="@drawable/example" android:layout_width="50dp" android:layout_height="50dp"/> 

可绘制的定义:

 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="#FFFFFF"/> <stroke android:color="#edf0f6" android:width="1dp"/> <corners android:radius="3dp"/> </shape> 

像这样创build和使用ValueAnimator:

 final ValueAnimator valueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), 0xFFFFFFFF, 0xff78c5f9); final GradientDrawable background = (GradientDrawable) view.getBackground(); currentAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(final ValueAnimator animator) { background.setColor((Integer) animator.getAnimatedValue()); } }); currentAnimation.setDuration(300); currentAnimation.start(); 

可绘制的过渡 :

查看定义:

 <View android:background="@drawable/example" android:layout_width="50dp" android:layout_height="50dp"/> 

可绘制的定义:

 <?xml version="1.0" encoding="utf-8"?> <transition xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape> <solid android:color="#FFFFFF"/> <stroke android:color="#edf0f6" android:width="1dp"/> <corners android:radius="3dp"/> </shape> </item> <item> <shape> <solid android:color="#78c5f9"/> <stroke android:color="#68aff4" android:width="1dp"/> <corners android:radius="3dp"/> </shape> </item> </transition> 

像这样使用TransitionDrawable:

 final TransitionDrawable background = (TransitionDrawable) view.getBackground(); background.startTransition(300); 

您可以通过在animation实例上调用.reverse()来反转animation。

还有其他一些方法来做animation,但这三个可能是最常见的。 我通常使用ValueAnimator。

你可以做一个对象animation师。 例如,我有一个targetView,我想改变你的背景颜色:

 int colorFrom = Color.RED; int colorTo = Color.GREEN; int duration = 1000; ObjectAnimator.ofObject(targetView, "backgroundColor", new ArgbEvaluator(), colorFrom, colorTo) .setDuration(duration) .start(); 

如果你想这样的彩色animation,

在这里输入图像说明

这段代码将帮助你:

 float[] hsv; int runColor; int hue = 0; hsv = new float[3]; // Transition color hsv[1] = 1; hsv[2] = 1; anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { hsv[0] = 360 * animation.getAnimatedFraction(); runColor = Color.HSVToColor(hsv); yourView.setBackgroundColor(runColor); } }); anim.setRepeatCount(Animation.INFINITE); anim.start(); 

另一个简单的方法是使用AlphaAnimation执行淡入淡出。

  1. 使您的视图为ViewGroup
  2. 在索引0处添加一个子视图,使用match_parent布局尺寸
  3. 给你的孩子和容器一样的背景
  4. 将容器的背景更改为目标颜色
  5. 使用AlphaAnimation淡出孩子。
  6. animation完成时移除子项(使用AnimationListener)

这是我在基本活动中用来更改背景的方法。 我使用代码生成的GradientDrawables,但可以适应。

  protected void setPageBackground(View root, int type){ if (root!=null) { Drawable currentBG = root.getBackground(); //add your own logic here to determine the newBG Drawable newBG = Utils.createGradientDrawable(type); if (currentBG==null) { if(Build.VERSION.SDK_INT<Build.VERSION_CODES.JELLY_BEAN){ root.setBackgroundDrawable(newBG); }else{ root.setBackground(newBG); } }else{ TransitionDrawable transitionDrawable = new TransitionDrawable(new Drawable[]{currentBG, newBG}); transitionDrawable.setCrossFadeEnabled(true); if(Build.VERSION.SDK_INT<Build.VERSION_CODES.JELLY_BEAN){ root.setBackgroundDrawable(transitionDrawable); }else{ root.setBackground(transitionDrawable); } transitionDrawable.startTransition(400); } } } 

更新:如果有人遇到同样的问题,我发现,出于某种原因在Android <4.3使用setCrossFadeEnabled(true)会导致一个不受欢迎的白色的效果,所以我不得不使用@Roman Minenok ValueAnimator方法切换到<4.3的纯色以上。

这是一个很好的function,允许这样做:

 public static void animateBetweenColors(final View viewToAnimateItBackground, final int colorFrom, final int colorTo, final int durationInMs) { final ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); colorAnimation.addUpdateListener(new AnimatorUpdateListener() { ColorDrawable colorDrawable = new ColorDrawable(colorFrom); @Override public void onAnimationUpdate(final ValueAnimator animator) { colorDrawable.setColor((Integer) animator.getAnimatedValue()); viewToAnimateItBackground.setBackgroundDrawable(colorDrawable); } }); if (durationInMs >= 0) colorAnimation.setDuration(durationInMs); colorAnimation.start(); } 

我发现ArgbEvaluator在Android源代码中使用的实现在转换颜色方面做得最好。 在使用HSV时,根据两种颜色的不同,这个过渡对我来说是跳过太多的色彩。 但是这个方法不行

如果您尝试简单地设置animationArgbEvaluatorValueAnimator按照以下build议使用ArgbEvaluator中的ValueAnimator

 ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); colorAnimation.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animator) { view.setBackgroundColor((int) animator.getAnimatedValue()); } }); colorAnimation.start(); 

然而,如果你像我一样想要将你的转换与用户input的某个用户手势或其他值相关联,那么ValueAnimator的帮助不大(除非你的目标是API 22以上),在这种情况下,你可以使用ValueAnimator.setCurrentFraction()方法)。 在API 22下方定位时,将您在ArgbEvaluator源代码中find的代码封装在您自己的方法中,如下所示:

 public static int interpolateColor(float fraction, int startValue, int endValue) { int startA = (startValue >> 24) & 0xff; int startR = (startValue >> 16) & 0xff; int startG = (startValue >> 8) & 0xff; int startB = startValue & 0xff; int endA = (endValue >> 24) & 0xff; int endR = (endValue >> 16) & 0xff; int endG = (endValue >> 8) & 0xff; int endB = endValue & 0xff; return ((startA + (int) (fraction * (endA - startA))) << 24) | ((startR + (int) (fraction * (endR - startR))) << 16) | ((startG + (int) (fraction * (endG - startG))) << 8) | ((startB + (int) (fraction * (endB - startB)))); } 

然后使用它,但是你希望。

最好的方法是使用ValueAnimator和ColorUtils.blendARGB

  ValueAnimator valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f); valueAnimator.setDuration(325); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { float fractionAnim = (float) valueAnimator.getAnimatedValue(); view.setColorBackground(ColorUtils.blendARGB(Color.parseColor("#FFFFFF") , Color.parseColor("#000000") , fractionAnim)); } }); valueAnimator.start();