如何在Android上动画化视图的背景颜色变化?
例如:
我有一个红色背景色的视图。视图的背景颜色变为蓝色。我怎样才能在颜色之间平滑过渡呢?
如果视图不能做到这一点,那么另一种选择是受欢迎的。
如何在Android上动画化视图的背景颜色变化?
例如:
我有一个红色背景色的视图。视图的背景颜色变为蓝色。我怎样才能在颜色之间平滑过渡呢?
如果视图不能做到这一点,那么另一种选择是受欢迎的。
当前回答
添加一个文件夹动画到res文件夹。(名称必须是animator)。添加一个动画资源文件。例如res/animator/fade.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="backgroundColor"
android:duration="1000"
android:valueFrom="#000000"
android:valueTo="#FFFFFF"
android:startOffset="0"
android:repeatCount="-1"
android:repeatMode="reverse" />
</set>
在Activity java文件中,调用这个
View v = getWindow().getDecorView().findViewById(android.R.id.content);
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.fade);
set.setTarget(v);
set.start();
其他回答
罗曼米诺克回答在kotlin和作为扩展函数
fun View.colorTransition(@ColorRes startColor: Int, @ColorRes endColor: Int, duration: Long = 250L){
val colorFrom = ContextCompat.getColor(context, startColor)
val colorTo = ContextCompat.getColor(context, endColor)
val colorAnimation: ValueAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo)
colorAnimation.duration = duration
colorAnimation.addUpdateListener {
if (it.animatedValue is Int) {
val color=it.animatedValue as Int
setBackgroundColor(color)
}
}
colorAnimation.start()
}
如果你想改变当前的背景色到新的颜色,那么你可以使用这个
fun View.colorTransition(@ColorRes endColor: Int, duration: Long = 250L){
var colorFrom = Color.TRANSPARENT
if (background is ColorDrawable)
colorFrom = (background as ColorDrawable).color
val colorTo = ContextCompat.getcolor(context, endColor)
val colorAnimation: ValueAnimator = ValueAnimator.ofObject(ArgbEvaluator(), colorFrom, colorTo)
colorAnimation.duration = duration
colorAnimation.addUpdateListener {
if (it.animatedValue is Int) {
val color=it.animatedValue as Int
setBackgroundColor(color)
}
}
colorAnimation.start()
}
使用
myView.colorTransition(R.color.bg_color)
根据视图获取背景颜色的方式以及获取目标颜色的方式,有几种不同的方法可以做到这一点。
前两个使用Android属性动画框架。
在以下情况下使用对象动画器:
视图的背景颜色定义为xml文件中的argb值。 你的视图之前已经由view设置了它的颜色。 视图的背景颜色定义在一个drawable中,它没有定义任何额外的属性,如笔画或角半径。 你的视图有它的背景颜色定义在一个可绘制的,你想要删除任何额外的属性,如笔画或角半径,请记住,删除额外的属性将不会动画。
对象动画器通过调用view来工作。setBackgroundColor替换已定义的drawable,除非它是ColorDrawable的实例,但它很少是。这意味着任何来自可绘制对象的额外背景属性(如描边或角)都将被删除。
在以下情况下使用值动画器:
你的视图有它的背景颜色定义在一个可绘制的,还设置属性,如笔画或角半径和你想改变它为一个新的颜色,这是在运行时决定的。
在以下情况下使用过渡绘制:
视图应该在部署前定义的两个可绘制对象之间切换。
我有一些性能问题与过渡绘图运行,而我正在打开一个抽屉布局,我还没有能够解决,所以如果你遇到任何意外的口吃,你可能会遇到相同的bug,我有。
如果你想使用StateLists可绘制对象或LayerLists可绘制对象,你必须修改Value Animator的例子,否则它会在最终的GradientDrawable background = (GradientDrawable) view.getBackground();线。
对象动画:
视图定义:
<View
android:background="#FFFF0000"
android:layout_width="50dp"
android:layout_height="50dp"/>
像这样创建并使用一个ObjectAnimator。
final ObjectAnimator backgroundColorAnimator = ObjectAnimator.ofObject(view,
"backgroundColor",
new ArgbEvaluator(),
0xFFFFFFFF,
0xff78c5f9);
backgroundColorAnimator.setDuration(300);
backgroundColorAnimator.start();
你也可以从xml中使用AnimatorInflater加载动画定义,就像XMight在Android中的objectAnimator animate backgroundColor of Layout
动画师的值:
视图定义:
<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>
像这样创建并使用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);
你可以通过在动画实例上调用.reverse()来反转动画。
还有其他制作动画的方法,但这三种可能是最常见的。我通常使用ValueAnimator。
我最终想出了一个(非常好的)解决这个问题的方法!
你可以使用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使用属性动画API的另一个解决方案的答案,在这个答案最初发布时还不可用。
你可以像这样使用ValueAnimator:
fun startColorAnimation(v: View) {
val colorStart = v.solidColor
val colorEnd = Color.RED
val colorAnim: ValueAnimator = ObjectAnimator.ofInt(v, "backgroundColor", colorStart, colorEnd)
colorAnim.setDuration(1000)
colorAnim.setEvaluator(ArgbEvaluator())
colorAnim.repeatCount = 1
colorAnim.repeatMode = ValueAnimator.REVERSE
colorAnim.start()
}
答案可以从很多方面给出。你也可以使用ValueAnimator的ofArgb(startColor,endColor)。
火灾> 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();