三、Property Animation动画的应用
在前面介绍的View Animation动画体系中,虽然使用起来十分方便,但也有十分多的局限性,例如只能支持透明度,位置,缩放和旋转动画,并且在动画执行时,视图实际上并没有移动,如果需要做动画的是可以用户交互的按钮控件则会带来很多的不便。在Android3.0之后,系统推出了Property Animation动画,这种机制可以将对象任意属性的修改实现过渡动画效果。
1.ObjectAnimator动画的应用
ObjectAnimator是Property Animation动画体系中最简单易用的一种方式,开发者只需要设置要改变的属性值和一些动画参数即可使用,例如若要实现视图以y方向为轴进行旋转操作,使用 如下代码实现:
//创建属性动画对象
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(animationImageView,"rotationY",0,360,0);
//设置动画时间
objectAnimator.setDuration(3000);
//开始动画
objectAnimator.start();
ObjectAnimator类的静态方法ofFloat()用于创建属性动画实例本身,与其类似的方法还有ofInt()与ofObject()。需要注意,这些方法第1个参数为要执行动画的视图,第2个参数为要发生动画改变的属性名,从第3个参数开始后面可以添加任意多个值,这些值代表了属性值改变的路径,例如上面示例代码表示将视图以y方向为轴从0°开始旋转到360°后再旋转回0°。
ObjectAnimator类继承自ValueAnimator,ValueAnimator类则更加灵活自由,其可以为自定义类的自定义属性做动画处理,后面会介绍,ValueAnimator类中提供了许多动画配置的方法,常用如下:
//设置动画执行时间
public ValueAnimator setDuration(long duration);
//设置延时执行
public void setStartDelay(long startDelay);
//设置动画循环次数
public void setRepeatCount(int value);
//设置动画循环模式
public void setRepeatMode(int value);
//设置动画执行时序模式
public void setInterpolator(TimeInterpolator value);
//开始执行动画
public void start();
//结束动画
public void end();
//取消动画
public void cancel();
//恢复动画
public void resume();
//暂停动画
public void pause();
需要注意,使用ObjectAnimator创建动画的属性必须实现set和get方法。
2.ValueAnimator实现更加灵活的自定义动画
ObjectAnimator是ValueAnimator的子类,可以理解,ValueAnimator要比ObjectAnimator更加灵活自由,其可以实现任意自定义属性的动画行为。示例代码如下:
//创建ValueAnimator实例
ValueAnimator valueAnimator = new ValueAnimator();
//设置动画的路径值
valueAnimator.setFloatValues(0,200,100,300,0);
//设置动画的执行时间
valueAnimator.setDuration(6000);
//添加动画执行监听
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
//这个方法会在每次动画值改变时调用
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
//设置视图的横坐标
animationImageView.setX((Float) valueAnimator.getAnimatedValue());
}
});
//执行动画
valueAnimator.start();
如果运行上面代码,可以看到视图在6s内从x坐标点为0的地方平移到200后再次回到100后再次移动到300最终回到原点0。
上面的示例代码只是演示了ValueAnimator的工作原理,开发者可以在onAnimationUpdate()方法中进行任意属性的修改。仅从上面演示代码并不能体现出ValueAnimator的强大之处,可以通过实现类似抛物线的动画来理解ValueAnimator的灵活之处,示例代码如下:
//创建ValueAnimator实例
final ValueAnimator animator = new ValueAnimator();
//示例进行抛物线动画 让控件从(0,0)点位置移动到x轴为400的位置,y轴方向做自由落体
animator.setObjectValues(new Point(0,0),new Point(400,0));
//设置动画时间
animator.setDuration(4000);
//设置时序为线性函数
animator.setInterpolator(new LinearInterpolator());
//由于抛物线运动在x轴和y轴上的速度变化并不相同 需要自定义枚举器
animator.setEvaluator(new TypeEvaluator<Point>() {
//这个枚举方法中传入的v值为动画执行的比例 0为初始状态 1为动画执行完成 开发者根据这个值模拟抛物线坐标
@Override
public Point evaluate(float v, Point o,Point t1) {
//创建Point对象 模拟抛物运动
Point point = new Point();
point.x = (int)((v*8)*100);
point.y = (int)((v*60)*(v*60)/4);
return point;
}
});
//监听动画执行
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
//设置视图位置
animationImageView.setX(((Point)valueAnimator.getAnimatedValue()).x);
animationImageView.setY(((Point)valueAnimator.getAnimatedValue()).y);
}
});
//执行动画
animator.start();
需要注意,Property Animation与View Animation最大的不同在于View Animation只是展示视图的界面动画,它并没有真正改变视图的属性,而Property Animation是实实在在的改变了发生动画控件的属性。
3.Property Animation动画的监听
ValueAnimator对象可以使用addListener()方法来添加监听者,接口方法如下:
//动画监听接口
public interface AnimatorListener {
//动画开始
void onAnimationStart(Animator var1);
//动画结束
void onAnimationEnd(Animator var1);
//动画取消
void onAnimationCancel(Animator var1);
//动画重复
void onAnimationRepeat(Animator var1);
}
4.使用PropertyValuesHolder进行动画复合
对于Property Animation,开发者可以通过ValueAnimator实现自定义的复合动画,也可以使用PropertyValuesHolder进行属性动画的复合操作,示例如下:
//创建子属性动画 翻转
PropertyValuesHolder holder = PropertyValuesHolder.ofFloat("rotationY",0,360,90);
//创建子属性动画 透明
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("alpha",1,0,1);
//进行动画复合
ObjectAnimator objectAnimation = ObjectAnimator.ofPropertyValuesHolder(animationImageView,holder,holder2);
//执行动画
objectAnimation.setDuration(3000);
objectAnimation.start();
三、Drawable Animation动画的应用
相比前两种动画模式,Drawable Animation动画要容易的多,其使用一组图像快速切换的原理来实现动画效果。
在Android Studio的drawable文件夹中添加一个animation文件,xml代码如下:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bird1" android:duration="200" />
<item android:drawable="@drawable/bird2" android:duration="200" />
<item android:drawable="@drawable/bird3" android:duration="200" />
<item android:drawable="@drawable/bird4" android:duration="200" />
<item android:drawable="@drawable/bird5" android:duration="200" />
<item android:drawable="@drawable/bird6" android:duration="200" />
<item android:drawable="@drawable/bird7" android:duration="200" />
<item android:drawable="@drawable/bird8" android:duration="200" />
</animation-list>
将需要展示动画的视图背景设置为这个drawable文件,示例如下:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/anmi_draw_list"
android:id="@+id/animatedImageView"/>
在需要开始动画时,调用如下代码即可:
//获取到drawable背景 调用start()方法开始动画
((AnimationDrawable)animationImageView.getBackground()).start();