如何在Android上为视图的背景色变化设置动画?
例如:
我的背景色为红色。 视图的背景颜色变为蓝色。 如何在颜色之间进行平滑过渡?
如果无法通过视图完成此操作,将欢迎使用其他方法。
#1楼
实现此目的的另一种简便方法是使用AlphaAnimation执行淡入。
- 使您的视图成为ViewGroup
- 将子视图添加到索引0,具有match_parent布局尺寸
- 给孩子提供与容器相同的背景
- 将容器的背景更改为目标颜色
- 使用AlphaAnimation淡出孩子。
- 动画完成后删除子级(使用AnimationListener)
#2楼
您可以将新的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();
为了与Android 2.x向后兼容,请使用Jake Wharton的Nine Old Androids库 。
在Android M中不赞成使用getColor
方法,因此您有两种选择:
如果使用支持库,则需要将
getColor
调用替换为:ContextCompat.getColor(this, R.color.red);
如果不使用支持库,则需要将
getColor
调用替换为:getColor(R.color.red);
#3楼
根据视图获取背景颜色的方式以及目标颜色的方式,有几种不同的方法可以执行此操作。
前两个使用Android Property Animation框架。
在以下情况下使用对象动画制作器 :
- 您的视图的背景色定义为xml文件中的
argb
值。 - 您的视图先前已通过
view.setBackgroundColor()
设置了颜色。 - 视图的背景色在可绘制对象中定义,该对象不定义任何额外的属性,例如笔触或拐角半径。
- 视图的背景色在可绘制对象中定义,并且要删除任何额外的属性,例如笔触或拐角半径,请记住,删除这些额外的属性不会产生动画效果。
对象动画师通过调用view.setBackgroundColor
来工作,该对象将替换已定义的drawable,除非它是ColorDrawable
的实例,但很少出现。 这意味着将删除可绘制对象中任何多余的背景属性(例如笔触或拐角)。
在以下情况下使用值动画器 :
- 视图的背景颜色在可绘制对象中定义,该对象还设置了诸如笔触或拐角半径的属性,并且您想将其更改为在运行时确定的新颜色。
如果满足以下条件,则使用Transition绘制 :
- 您的视图应在部署之前已定义的两个可绘制对象之间切换。
我在打开无法解决的DrawerLayout时运行的Transition可绘制对象遇到一些性能问题,因此,如果遇到任何意外的卡顿,您可能会遇到与我相同的错误。
如果要使用StateLists可绘制对象或LayerLists可绘制对象 ,则必须修改Value Animator示例,否则它将在final 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();
您还可以像XMight在Android object中那样使用AnimatorInflater从xml中加载动画定义。
价值动画师 :
查看定义:
<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。
#4楼
这是一个不错的功能,它可以实现以下目的:
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();
}
}
在科特林:
@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()
}
}
#5楼
这是我在基本活动中用于更改背景的方法。 我正在使用在代码中生成的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切换为纯色以上。
来源:oschina
链接:https://my.oschina.net/stackoom/blog/3206655