Android上视图背景颜色的动画变化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2614545/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Animate change of view background color on Android
提问by hpique
How do you animate the change of background color of a view on Android?
你如何在 Android 上为视图背景颜色的变化设置动画?
For example:
例如:
I have a view with a red background color. The background color of the view changes to blue. How can I do a smooth transition between colors?
我有一个红色背景色的视图。视图的背景颜色变为蓝色。如何在颜色之间进行平滑过渡?
If this can't be done with views, an alternative will be welcome.
如果这不能通过视图完成,则欢迎使用替代方法。
回答by Roman Minenok
You can use new Property Animation Apifor color animation:
您可以使用新的Property Animation Api进行彩色动画:
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();
For backward compatibility with Android 2.x use Nine Old Androids libraryfrom Jake Wharton.
为了与 Android 2.x 向后兼容,请使用Jake Wharton 的九个旧 Android 库。
The getColor
method was deprecated in Android M, so you have two choices:
该getColor
方法在 Android M 中已弃用,因此您有两种选择:
If you use the support library, you need to replace the
getColor
calls with:ContextCompat.getColor(this, R.color.red);
if you don't use the support library, you need to replace the
getColor
calls with:getColor(R.color.red);
如果使用支持库,则需要将
getColor
调用替换为:ContextCompat.getColor(this, R.color.red);
如果您不使用支持库,则需要将
getColor
调用替换为:getColor(R.color.red);
回答by idolize
I ended up figuring out a (pretty good) solution for this problem!
我最终为这个问题找到了一个(相当不错的)解决方案!
You can use a TransitionDrawableto accomplish this. For example, in an XML file in the drawable folder you could write something like:
您可以使用TransitionDrawable来完成此操作。例如,在 drawable 文件夹中的 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>
Then, in your XML for the actual View you would reference this TransitionDrawable in the android:background
attribute.
然后,在实际视图的 XML 中,您将在android:background
属性中引用此 TransitionDrawable 。
At this point you can initiate the transition in your code on-command by doing:
此时,您可以通过执行以下操作在您的代码中启动转换:
TransitionDrawable transition = (TransitionDrawable) viewObj.getBackground();
transition.startTransition(transitionTime);
Or run the transition in reverse by calling:
或者通过调用反向运行转换:
transition.reverseTransition(transitionTime);
See Roman's answerfor another solution using the Property Animation API, which wasn't available at the time this answer was originally posted.
有关使用 Property Animation API 的另一个解决方案,请参阅Roman 的答案,该答案在最初发布此答案时不可用。
回答by Mattias
Depending on how your view gets its background color and how you get your target color there are several different ways to do this.
根据您的视图如何获得其背景颜色以及您如何获得目标颜色,有几种不同的方法可以做到这一点。
The first two uses the Android Property Animationframework.
前两个使用Android 属性动画框架。
Use a Object Animatorif:
在以下情况下使用对象动画器:
- Your view have its background color defined as a
argb
value in a xml file. - Your view have previously had its color set by
view.setBackgroundColor()
- Your view have its background color defined in a drawable that DOES NOTdefines any extra properties like stroke or corner radiuses.
- Your view have its background color defined in a drawable and you want to remove any extra properties like stroke or corner radiuses, keep in mind that the removal of the extra properties will not animated.
- 您的视图将其背景颜色定义为
argb
xml 文件中的值。 - 您的视图之前已设置其颜色
view.setBackgroundColor()
- 您的视图在 drawable 中定义了它的背景颜色,它不定义任何额外的属性,如笔划或圆角半径。
- 您的视图在 drawable 中定义了它的背景颜色,并且您想要删除任何额外的属性,如笔划或角半径,请记住,额外属性的删除不会动画化。
The object animator works by calling view.setBackgroundColor
which replaces the defined drawable unless is it an instance of a ColorDrawable
, which it rarely is. This means that any extra background properties from a drawable like stroke or corners will be removed.
对象动画师通过调用view.setBackgroundColor
which 替换定义的可绘制对象来工作,除非它是 a 的实例ColorDrawable
,但很少是。这意味着来自可绘制对象的任何额外背景属性(如笔画或角)都将被删除。
Use a Value Animatorif:
在以下情况下使用Value Animator:
- Your view have its background color defined in a drawable that also sets properties like the stroke or corner radiuses AND you want to change it to a new color that is decided while running.
- 您的视图在可绘制对象中定义了其背景颜色,该对象还设置了笔划或角半径等属性,并且您希望将其更改为在运行时决定的新颜色。
Use a Transition drawableif:
在以下情况下使用Transition drawable:
- Your view should switch between two drawable that have been defined before deployment.
- 您的视图应该在部署之前定义的两个可绘制对象之间切换。
I have had some performance issues with Transition drawables that runs while I am opening a DrawerLayout that I haven't been able to solve, so if you encounter any unexpected stuttering you might have run into the same bug as I have.
我在打开 DrawerLayout 时运行的 Transition drawable 遇到了一些性能问题,但我无法解决,所以如果您遇到任何意外的卡顿,您可能会遇到与我相同的错误。
You will have to modify the Value Animator example if you want to use a StateLists drawableor a LayerLists drawable, otherwise it will crash on the final GradientDrawable background = (GradientDrawable) view.getBackground();
line.
如果要使用StateLists drawable或LayerLists drawable,则必须修改 Value Animator 示例,否则它会在线上崩溃final GradientDrawable background = (GradientDrawable) view.getBackground();
。
View definition:
查看定义:
<View
android:background="#FFFF0000"
android:layout_width="50dp"
android:layout_height="50dp"/>
Create and use a ObjectAnimator
like this.
创建和使用ObjectAnimator
这样的。
final ObjectAnimator backgroundColorAnimator = ObjectAnimator.ofObject(view,
"backgroundColor",
new ArgbEvaluator(),
0xFFFFFFFF,
0xff78c5f9);
backgroundColorAnimator.setDuration(300);
backgroundColorAnimator.start();
You can also load the animation definition from a xml using a AnimatorInflater like XMight does in Android objectAnimator animate backgroundColor of Layout
您还可以使用 AnimatorInflater 从 xml 加载动画定义,就像 XMight 在Android objectAnimator 中对布局的动画背景颜色所做的那样
View definition:
查看定义:
<View
android:background="@drawable/example"
android:layout_width="50dp"
android:layout_height="50dp"/>
Drawable definition:
可绘制定义:
<?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>
Create and use a ValueAnimator like this:
像这样创建和使用 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 definition:
查看定义:
<View
android:background="@drawable/example"
android:layout_width="50dp"
android:layout_height="50dp"/>
Drawable definition:
可绘制定义:
<?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>
Use the TransitionDrawable like this:
像这样使用 TransitionDrawable:
final TransitionDrawable background = (TransitionDrawable) view.getBackground();
background.startTransition(300);
You can reverse the animations by calling .reverse()
on the animation instance.
您可以通过调用.reverse()
动画实例来反转动画。
There are some other ways to do animations but these three is probably the most common. I generally use a ValueAnimator.
还有一些其他方法可以制作动画,但这三种可能是最常见的。我通常使用 ValueAnimator。
回答by ademar111190
You can make an object animator. For example, I have a targetView and I want to change your background color:
您可以制作对象动画师。例如,我有一个 targetView,我想更改您的背景颜色:
int colorFrom = Color.RED;
int colorTo = Color.GREEN;
int duration = 1000;
ObjectAnimator.ofObject(targetView, "backgroundColor", new ArgbEvaluator(), colorFrom, colorTo)
.setDuration(duration)
.start();
回答by RBK
If you want color animation like this,
如果你想要这样的彩色动画,
this code will help you:
此代码将帮助您:
ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
anim.setDuration(2000);
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();
回答by Rasoul Miri
best way is to use ValueAnimatorand ColorUtils.blendARGB
最好的方法是使用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.setBackgroundColor(ColorUtils.blendARGB(Color.parseColor("#FFFFFF")
, Color.parseColor("#000000")
, fractionAnim));
}
});
valueAnimator.start();
回答by Stephane JAIS
Another easy way to achieve this is to perform a fade using AlphaAnimation.
实现此目的的另一种简单方法是使用 AlphaAnimation 执行淡入淡出。
- Make your view a ViewGroup
- Add a child view to it at index 0, with match_parent layout dimensions
- Give your child the same background as the container
- Change to background of the container to the target color
- Fade out the child using AlphaAnimation.
- Remove the child when the animation is complete (using an AnimationListener)
- 使您的视图成为 ViewGroup
- 在索引 0 处添加一个子视图,具有 match_parent 布局尺寸
- 为您的孩子提供与容器相同的背景
- 将容器的背景更改为目标颜色
- 使用 AlphaAnimation 淡出孩子。
- 动画完成时移除子项(使用 AnimationListener)
回答by scottyab
This is the method I use in a Base Activity to change background. I'm using GradientDrawables generated in code, but could be adapted to suit.
这是我在 Base Activity 中用于更改背景的方法。我正在使用代码中生成的 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);
}
}
}
update:In case anyone runs in to same issue I found, for some reason on Android <4.3 using setCrossFadeEnabled(true)
cause a undesirable white out effect so I had to switch to a solid colour for <4.3 using @Roman Minenok ValueAnimator method noted above.
更新:如果有人遇到相同的问题,我发现,出于某种原因,在 Android <4.3 上使用setCrossFadeEnabled(true)
会导致不受欢迎的白化效果,所以我不得不使用上面提到的@Roman Minenok ValueAnimator 方法切换到 <4.3 的纯色。
回答by android developer
Here's a nice function that allows this:
这是一个很好的函数,允许这样做:
public static void animateBetweenColors(final @NonNull View viewToAnimateItsBackground, final int colorFrom,
final int colorTo, final int durationInMs) {
final ColorDrawable colorDrawable = new ColorDrawable(durationInMs > 0 ? colorFrom : colorTo);
ViewCompat.setBackground(viewToAnimateItsBackground, colorDrawable);
if (durationInMs > 0) {
final ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo);
colorAnimation.addUpdateListener(animator -> {
colorDrawable.setColor((Integer) animator.getAnimatedValue());
ViewCompat.setBackground(viewToAnimateItsBackground, colorDrawable);
});
colorAnimation.setDuration(durationInMs);
colorAnimation.start();
}
}
And in Kotlin:
在 Kotlin 中:
@JvmStatic
fun animateBetweenColors(viewToAnimateItsBackground: View, colorFrom: Int, colorTo: Int, durationInMs: Int) {
val colorDrawable = ColorDrawable(if (durationInMs > 0) colorFrom else colorTo)
ViewCompat.setBackground(viewToAnimateItsBackground, colorDrawable)
if (durationInMs > 0) {
val colorAnimation = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo)
colorAnimation.addUpdateListener { animator: ValueAnimator ->
colorDrawable.color = (animator.animatedValue as Int)
ViewCompat.setBackground(viewToAnimateItsBackground, colorDrawable)
}
colorAnimation.duration = durationInMs.toLong()
colorAnimation.start()
}
}
回答by Palak Darji
Answer is given in many ways. You can also use ofArgb(startColor,endColor)
of ValueAnimator
.
答案是通过多种方式给出的。您还可以使用ofArgb(startColor,endColor)
的ValueAnimator
。
for API > 21:
对于 API > 21:
int cyanColorBg = ContextCompat.getColor(this,R.color.cyan_bg);
int purpleColorBg = ContextCompat.getColor(this,R.color.purple_bg);
ValueAnimator valueAnimator = ValueAnimator.ofArgb(cyanColorBg,purpleColorBg);
valueAnimator.setDuration(500);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
relativeLayout.setBackgroundColor((Integer)valueAnimator.getAnimatedValue());
}
});
valueAnimator.start();