如何在Android上动画化视图的背景颜色变化?
例如:
我有一个红色背景色的视图。视图的背景颜色变为蓝色。我怎样才能在颜色之间平滑过渡呢?
如果视图不能做到这一点,那么另一种选择是受欢迎的。
如何在Android上动画化视图的背景颜色变化?
例如:
我有一个红色背景色的视图。视图的背景颜色变为蓝色。我怎样才能在颜色之间平滑过渡呢?
如果视图不能做到这一点,那么另一种选择是受欢迎的。
当前回答
我发现ArgbEvaluator在Android源代码中使用的实现在转换颜色方面做得最好。当使用HSV时,根据两种颜色,过渡对我来说跳过了太多的色调。但是这个方法没有。
如果你想简单地做动画,使用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();
然而,如果你像我一样,想要将你的转换与一些用户手势或其他输入传递的值绑定在一起,ValueAnimator就没有多大帮助了(除非你的目标是API 22及以上,在这种情况下,你可以使用ValueAnimator. setcurrentfraction()方法)。当目标是API 22以下的代码时,将ArgbEvaluator源代码中找到的代码包装在你自己的方法中,如下所示:
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))));
}
你想怎么用就怎么用。
其他回答
你可以使用新的属性动画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();
向后兼容Android 2。x使用Jake Wharton的九个旧android库。
getColor方法在Android M中已弃用,所以你有两个选择:
如果你使用支持库,你需要用以下语句替换getColor调用: ContextCompat。色鬼(这个,R.color.red); 如果你不使用支持库,你需要将getColor调用替换为: 色鬼(R.color.red);
实现这一点的另一种简单方法是使用AlphaAnimation执行渐隐。
将视图设置为ViewGroup 在索引0处添加一个子视图,使用match_parent布局维度 给你的孩子与容器相同的背景 更改容器的背景为目标颜色 使用AlphaAnimation淡出子动画。 当动画完成时删除子动画(使用AnimationListener)
罗曼米诺克回答在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)
这里有一个很好的函数可以做到这一点:
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();
}
}
在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()
}
}
这是我在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);
}
}
}
更新:如果有人遇到同样的问题,我发现,出于某种原因,在Android <4.3使用setCrossFadeEnabled(true)导致一个不受欢迎的白色效果,所以我不得不切换到一个纯色<4.3使用@Roman Minenok ValueAnimator方法上面提到。