安卓中动画分成两类
一种是传统动画,如:补间动画,帧动画,其本质是canvas的矩阵变换
另一种是属性动画,由谷歌从Android3.0以后推出
传统动画仅仅是视觉效果,并不会实际改变view的属性,比如:平移动画不会改变view的原来坐标,如果需要点击view还是要点击原来的位置。而属性动画不同,它是真正的改变view的属性(成员变量)。
我们使用属性动画,需要掌握5个类
- ObjectAnimator
- ValueAnimator
- PropertyValueHolder
- TypeEvaluator
- Interpolator
首先,我们创建一个ImageView,使用默认的安卓启动图标
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:onClick="startAnimation"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
下面是属性动画ObjectAnimator的基础用法
public void startAnimation(View view) {
ImageView iv = (ImageView) view;
//注意第二个参数,只要view里面有setXXX()方法就可以通过反射达到变化的目的
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(iv, "translationX", 0f, 100f);
objectAnimator.setDuration(500);
objectAnimator.start();
}

ObjectAnimator.gif
如果想要多个动画同时执行
方法1.设置动画监听,同步操作其他的属性
public void startAnimation(View view) {
final ImageView iv = (ImageView) view;
//iv显然没有setXiaoming的方法,内部做了异常处理
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(iv, "xiaoming", 0f, 100f);
objectAnimator.setDuration(500);
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 监听动画回调
//animation.getAnimatedFraction();//动画执行的百分比 0~1 //API 12+
float value = (float) animation.getAnimatedValue();//得到0f~100f当中的这个时间点对应的值
iv.setScaleX(0.5f+value/200);
iv.setScaleY(0.5f+value/200);
//iv.setTranslationX(value);
}
});
objectAnimator.start();
}

设置动画监听,同步操作其他的属性.gif
方法2.使用ValueAnimator,如果只需要监听值变化就用ValueAnimator
public void startAnimation(View view) {
final ImageView iv = (ImageView) view;
ValueAnimator animator = ValueAnimator.ofFloat(0f, 200f);
animator.setDuration(200);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();//得到0f~100f当中的这个时间点对应的值
iv.setScaleX(0.5f + value / 200);
iv.setScaleY(0.5f + value / 200);
}
});
animator.start();
}

ValueAnimator.gif
方法3.使用PropertyValuesHolder
public void startAnimation(View view) {
final ImageView iv = (ImageView) view;
PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("alpha", 1f, 0.5f);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0.5f);
PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0.5f);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(iv, holder1, holder2, holder3);
animator.setDuration(200);
animator.start();
}

PropertyValuesHolder.gif
方法4.动画集合AnimatorSet
public void startAnimation(View view) {
final ImageView iv = (ImageView) view;
ObjectAnimator animator1 = ObjectAnimator.ofFloat(iv, "translationX", 0f, 100f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(iv, "alpha", 0f, 1f);
// animator2.setStartDelay(startDelay)//设置延迟执行
ObjectAnimator animator3 = ObjectAnimator.ofFloat(iv, "scaleX", 0f, 2f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(500);
// animatorSet.play(animator3).with(animator2).after(animator1);//animator1在前面
// animatorSet.play(animator3).with(animator2).before(animator1);//animator1在后面
// animatorSet.playTogether(animator1,animator2,animator3);//同时执行
animatorSet.playSequentially(animator1, animator2, animator3);//按顺序执行
animatorSet.start();
}

AnimatorSet.gif
如果我们要实现一个自由落体抛物线动画,可以使用估值器TypeEvaluator
public void startAnimation(View view) {
final ImageView iv = (ImageView) view;
ObjectAnimator objectAnimator = new ObjectAnimator();
objectAnimator.setDuration(2000);
objectAnimator.setObjectValues(new PointF(0, 0));
final PointF pointF = new PointF();
objectAnimator.setEvaluator(new TypeEvaluator() {
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
//估值计算方法---可以在执行的过程当中干预改变属性的值---做效果:用自己的算法来控制
//不断地去计算修改坐标
//x匀速运动 x=v*t
pointF.x = 400f * (fraction);
//加速度 y=vt=1/2*g*t*t
pointF.y = (float) (10f * 0.5f * 9.8f * Math.pow(fraction * 5, 2));
return pointF;
}
});
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
PointF pointF1 = (PointF) animation.getAnimatedValue();
iv.setX(pointF1.x);
iv.setY(pointF1.y);
}
});
objectAnimator.start();
}

自由落体抛物线.gif
动画执行过程,我们想要控制它的执行速度,可以使用插值器(加速器)Interpolater,下面介绍了几种常用的插值器
public void startAnimation(View view) {
final ImageView iv = (ImageView) view;
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationY", 0f,1000f);
oa.setDuration(800);
oa.setInterpolator(new AccelerateDecelerateInterpolator());
oa.start();
}

AccelerateDecelerateInterpolator 加速减速插值器 .png

AccelerateDecelerateInterpolator .gif

AccelerateInterpolator 加速插值器.png

AccelerateInterpolator .gif

AnticipateInterpolator 回荡秋千插值器 .png

AnticipateInterpolator.gif

AnticipateOvershootInterpolator.png

AnticipateOvershootInterpolator.gif

BounceInterpolator 弹跳插值器.png

BounceInterpolator .gif

CycleInterpolator 正弦周期变化插值器 .png

CycleInterpolator .gif

DecelerateInterpolator 减速插值器.png

DecelerateInterpolator .gif

OvershootInterpolator.png

OvershootInterpolator.gif
网友评论