属性动画(Property Animation)可以满足大部分的动画需求,可以改变该动画对象的大部分属性,例如Translate平移,Scale缩放,Rotate旋转,Alpha透明度。和补间动画(View Animation或者Tween Animation)的区别是,补间动画的属性改变了以后,如果对象在屏幕中的位置改变了,那么消息响应在屏幕上的位置仍然不变,也就是说变的仅仅只是对象在屏幕上显示的地方而已,响应的位置还是原来的地方。但属性动画不同,对象的位置变了以后,响应的位置也随之改变。
下面我们来介绍一下自我感觉几个比较重要的类以及方法:
(1)ObjectAnimator类,最普通的动画执行类,可以支持单个动画的播放效果
(2)PropertyValuesHolder类,可以定义多个动画,然后给ObjectAnimator类一起执行,相当于同时执行多个动画效果
(3)ValueAnimator类,可以定义动画属性的各个值
(4)AnimatorSet类,用来播放一组动画,相当于PropertyValuesHolder类的执行效果
setDuration():定义动画完成的时间
setRepeatCount():定义动画的重复次数
ofFloat():想要执行或者修改的动画属性,平移,缩放,旋转,透明度等,下面的Demo会具体介绍
和Activity的生命周期差不多,Animation也有相类似的周期,开始,结束,取消,重放。
注:objectAnimator是ObjectAnimator的对象
objectAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
以下的这些方法又和上面的方法不同。上面的方法是在什么情况下调用,下面的方法是执行什么样的情况,注意区分
objectAnimator.start();
objectAnimator.end();
objectAnimator.cancel();
objectAnimator.pause();
objectAnimator.resume();
start方法让动画开始执行
end方法结束动画的执行
cancel方法是取消动画的执行
结束和取消的区别是,结束是让动画停留在动画执行完成后的状态,取消则是让动画停留在当前状态
pause是暂停动画的执行
resume是继续播放暂停的动画
下面我们以一个Demo来看看,首先是xml布局文件:
button_one_animation.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试按钮"
android:id="@+id/test_button_btn"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="结束"
android:id="@+id/end_btn"
android:layout_marginTop="112dp"
android:layout_below="@+id/test_button_btn"
android:layout_alignLeft="@+id/pause_btn"
android:layout_alignStart="@+id/pause_btn" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="取消"
android:id="@+id/cancel_btn"
android:layout_alignTop="@+id/end_btn"
android:layout_toRightOf="@+id/test_button_btn"
android:layout_toEndOf="@+id/test_button_btn" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止"
android:id="@+id/pause_btn"
android:layout_below="@+id/end_btn"
android:layout_toLeftOf="@+id/test_button_btn"
android:layout_toStartOf="@+id/test_button_btn" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="重放"
android:id="@+id/resume_btn"
android:layout_alignTop="@+id/pause_btn"
android:layout_alignLeft="@+id/cancel_btn"
android:layout_alignStart="@+id/cancel_btn" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始"
android:id="@+id/start_btn"
android:layout_above="@+id/cancel_btn"
android:layout_centerHorizontal="true" />
</RelativeLayout>
然后是主要的类:
ButtonOneAnimation.java
我们一点一点来看,先是一些变量基本的定义
public class ButtonOneAnimation extends Activity implements View.OnClickListener{
private ObjectAnimator objectAnimator;
private ValueAnimator valueAnimator;
private Button testButtonBtn;
private Button startBtn; //开始按钮
private Button endBtn; //结束按钮
private Button cancelBtn; //取消按钮
private Button pauseBtn; //停止按钮
private Button resumeBtn; //重放按钮
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.button_one_animation);
testButtonBtn = (Button)findViewById(R.id.test_button_btn);
startBtn = (Button)findViewById(R.id.start_btn);
endBtn = (Button)findViewById(R.id.end_btn);
cancelBtn = (Button)findViewById(R.id.cancel_btn);
pauseBtn = (Button)findViewById(R.id.pause_btn);
resumeBtn = (Button)findViewById(R.id.resume_btn);
testButtonBtn.setOnClickListener(this);
startBtn.setOnClickListener(this);
endBtn.setOnClickListener(this);
cancelBtn.setOnClickListener(this);
pauseBtn.setOnClickListener(this);
resumeBtn.setOnClickListener(this);
}
}
然后是响应函数,在响应函数的case R.id.start_btn中,调用了4个函数,分别代表着4个类的执行
@Override
public void onClick(View v){
int id = v.getId();
switch (id){
case R.id.start_btn:
objectAnimatorDemo(); //ObjectAnimatorDemo类
//propertyValuesHolderDemo(); //PropertyValuesHolderDemo类
//valueAnimatorDemo(); //ValueAnimatorDemo类
//animatorSetDemo(); //AnimatorSetDemo类
break;
case R.id.end_btn:
objectAnimator.end();
break;
case R.id.cancel_btn:
objectAnimator.cancel();
break;
case R.id.pause_btn:
objectAnimator.pause();
break;
case R.id.resume_btn:
objectAnimator.resume();
break;
default:
break;
}
}
最后就是4个类的实现方式,注意ObjectAnimator类,ofFloat的第二个参数:rotation旋转,translation平移,scale拉伸,alpha平移
//使用ObjectAnimator类来执行动画
public void objectAnimatorDemo(){
//ofFloat的第一个参数代码想要哪个View来播放,第二个参数代表不同的动画形式
objectAnimator = ObjectAnimator.ofFloat(testButtonBtn, "rotation", 0.0F, 360.0F); //绕着中心点旋转
//objectAnimator = ObjectAnimator.ofFloat(testButtonBtn, "rotationX", 0.0F, 360.0F); //绕着x轴旋转
//objectAnimator = ObjectAnimator.ofFloat(testButtonBtn, "rotationY", 0.0F, 360.0F); //绕着y轴旋转
//objectAnimator = ObjectAnimator.ofFloat(testButtonBtn, "translationX", 0.0F, 360.0F); //沿着x轴移动多少个距离
//objectAnimator = ObjectAnimator.ofFloat(testButtonBtn, "translationY", 0.0F, 360.0F); //沿着y轴移动多少个距离
//objectAnimator = ObjectAnimator.ofFloat(testButtonBtn, "alpha", 1.0F, 0.0F, 1.0F); //透明度
//objectAnimator = ObjectAnimator.ofFloat(testButtonBtn, "scaleX", 1.0F, 2F); //沿着x轴拉伸
//objectAnimator = ObjectAnimator.ofFloat(testButtonBtn, "scaleY", 1.0F, 2F); //沿着y轴拉伸
objectAnimator.setDuration(1000); //定义动画的完成时间
objectAnimator.setRepeatCount(5); //定义动画的重复次数
objectAnimator.setRepeatMode(ObjectAnimator.RESTART);
objectAnimator.start();
}
//用PropertyValuesHolder类来播放一组动画(多个动画一起执行)
public void propertyValuesHolderDemo(){
PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1f, 0f, 1f);
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("translationX", 0.0F, 360.0F);
objectAnimator.ofPropertyValuesHolder(testButtonBtn, alpha, pvhX).setDuration(1000).start();
}
//用ValueAnimator类来控制动画的值属性
public void valueAnimatorDemo(){
valueAnimator = new ValueAnimator();
valueAnimator.setDuration(3000);
valueAnimator.setObjectValues(new PointF(0, 0));
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setEvaluator(new TypeEvaluator<PointF>() {
@Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
PointF point = new PointF();
point.x = 200 * fraction * 3; //水平距离
point.y = 0.5f * 200 * (fraction * 3) * (fraction * 3); //垂直距离
return point;
}
});
valueAnimator.start();
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
PointF point = (PointF) animation.getAnimatedValue();
testButtonBtn.setX(point.x);
testButtonBtn.setY(point.y);
}
});
}
//用AnimatorSet类来播放一组动画,和前面的PropertyValuesHolder类效果相似
public void animatorSetDemo(){
ObjectAnimator animator1 = ObjectAnimator.ofFloat(testButtonBtn, "alpha", 1f, 0f, 1f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(testButtonBtn, "translationX", 0.0F, 360.0F);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(2000);
animatorSet.setInterpolator(new LinearInterpolator());
animatorSet.playTogether(animator1, animator2);
animatorSet.start();
}
PS:过几天我会放上Demo执行后的效果演示