一、传统的2D动画—补间动画+帧动画
实现的本质是什么?canvas绘制的---矩阵变换Matrix
补间动画是一种设定动画开始状态、结束状态,其中间的变化由系统计算补充。这也是他叫做补间动画的原因。
补间动画由Animation类来实现具体效果,包括平移(TranslateAnimation)、缩放(ScaleAnimation)、旋转(RotateAnimation)、透明度(AlphaAnimation)四个子类,四种变化。
二、属性动画
属性动画基础
API 3.0以后。
1.属性动画的系统使用;
2.案例
3.源码解析
4.结合前面一些特效+属性动画—综合案例
1.什么是属性动画?属性动画有什么特点?
比如
button.setTranslationX(200);
和传统补间动画的区别:—会改变view的实际属性。比如:改变button的位置,平移后的状态还是可以被点击的
2.属性动画
3.0_API以下的兼容方案:NineOldAndroid.jar
主要几个类
1.ObjectAnimator
2.ValueAnimator
3.PropertyValueHolder
4. TypeEvaluator 估值器---改变算法--改变值
5. Interpolator 插值器---控制计算的速度
Facebook Rebound 弹性动画库
属性动画效率高 还是补间动画效率高-- 补间动画
动画基本使用
动画1. 直接操作属性
对应代码
private void startAnimation1() {
//补间动画
//Animation loadAnimation = AnimationUtils.loadAnimation(this,R.anim)
//属性动画 的属性
ivTest.setTranslationX(120);//平移
ivTest.setScaleX(1.3f);//缩放
ivTest.setAlpha(0.5f);//透明度
ivTest.setRotation(20);//旋转
// ivTest.setBackgroundColor(color);//颜色渐变
}
动画2. OjbectAnimator基本使用
使用ObjectAnimator 平移
对应代码
//属性动画基本使用
private void startAnimation2() {
//参数 1 那个控件 参数2 属性的那种动画 (通过反射的方式) 参数3 数值 不断赋值 从0 到200
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(ivTest, "translationX", 0f, 200f);//平移
// ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(ivTest,"backgroundColor", red,green);//颜色
objectAnimator.setDuration(500);
objectAnimator.start();
}
多个动画同时执行
动画3 方法1: 设置动画监听 同步操作其他属性
//多个动画同时执行
private void startAnimation3() {
//方法1;----------------------- 设置动画监听 同步操作其他属性-------------
//参数 1 那个控件 参数2 属性的那种动画 (通过反射的方式) 参数3 数值 不断赋值 从0 到200
// @SuppressLint("ObjectAnimatorBinding") ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(ivTest, "test", 0f, 200f);//平移
@SuppressLint("ObjectAnimatorBinding") ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(ivTest, "setTranslationX", 0f, 100f);//平移
//实际这个操作 是 ivTest 身上的属性 叫做test; 如果参数 1 是this 则是当前java类的方法
//TODO 第二个参数是正在动画化的属性的名称 如果随便写 也可以 需要在AnimatorUpdateListener 中完成相应的动画
objectAnimator.setDuration(500);//持续时间
//添加监听 同步操作其他属性
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//监听动画回调
// animation.getAnimatedFraction(); //得到动画执行的百分比 0 - 1;
// animation.getAnimatedValue();//得到0f-100f当中的这个时间点对应的值
float value = (float) animation.getAnimatedValue();//得到0f-100f当中的这个时间点对应的值
Log.d(TAG, "onAnimationUpdate: value = " + value);
// ivTest.setScaleX(value/100);
// ivTest.setScaleY(value/100);
ivTest.setScaleX(0.5f + value / 200);
ivTest.setScaleY(0.5f + value / 200);
// ivTest.setTranslationX(value);
}
});
objectAnimator.start();
objectAnimator.setRepeatCount(2);//设置重复次数
// objectAnimator.setRepeatCount(ValueAnimator.INFINITE);//无限
// objectAnimator.setRepeatMode(ValueAnimator.RESTART);//重新开始
// objectAnimator.setRepeatMode(ValueAnimator.REVERSE);//翻转
// 设置其他监听
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) {
}
});
}
动画4 ,方法2 使用valueAnimator 只需要监听值的变化
同样的动画
public void startAnimator4() {
//添加监听 适配器模式
// objectAnimator.addListener(new AnimatorListenerAdapter() {
// });
//方法2;----------------------- 使用 ValueAnimator -----只需要监听值的变化-------
ValueAnimator animator = ValueAnimator.ofFloat(0f, 100f);
animator.setDuration(200);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();//得到0f-100f当中的这个时间点对应的值
Log.d(TAG, "onAnimationUpdate: value = " + value);
// ivTest.setScaleX(value/100);
// ivTest.setScaleY(value/100);
ivTest.setScaleX(0.5f + value / 200);
ivTest.setScaleY(0.5f + value / 200);
}
});
animator.start();
}
动画5 方法3 PropertyValuesHolder
对应代码
public void startAnimator5() {
//方法3 PropertyValuesHolder
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 objectAnimator = ObjectAnimator.ofPropertyValuesHolder(ivTest, holder1, holder2, holder3);
objectAnimator.setDuration(200);
objectAnimator.start();
}
动画6 动画集合AnimatorSet
对应代码
public void startAnimator6() {
//动画集合 AnimatorSet
ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(ivTest, "translationX", 0f, 100f);//平移
ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(ivTest, "scaleX", 1f, 2f);//平移
ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(ivTest, "scaleY", 1f, 2f);//平移
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(200);
// animatorSet.playTogether(objectAnimator1);
animatorSet.playTogether(objectAnimator1, objectAnimator2, objectAnimator3);
// animatorSet.playSequentially(objectAnimator1,objectAnimator2,objectAnimator3);//按照顺序执行
animatorSet.start();
// objectAnimator1和 objectAnimator2同时开启动画, objectAnimator2 在 objectAnimator3 的后面
// animatorSet.play(objectAnimator1).with(objectAnimator2).after(objectAnimator3);
}
动画7 实现抛物线动画 估值器的使用
对应代码
/**
* 实现一个抛物线的效果--购物车动画.股指数-- 重力加速度
*/
public void startAnimator7() {
//思路
/**
* X:匀速
* y: 加速度 y = vt = 1/2*g*t*t
* 使用估值器 setEvaluator
*
*/
ValueAnimator valueAnimator = new ValueAnimator();
// valueAnimator.setInterpolator(); //设置
// valueAnimator.setEvaluator();
valueAnimator.setDuration(1000);
//这里约束 animator 的约束 是pointf
valueAnimator.setObjectValues(new PointF(0, 0));
//这是从 00 到100,100 按照3000 的时间自己进行估值计算
// valueAnimator.setObjectValues(new PointF(0,0),new PointF(100,100));
//对这个点进行操作
final PointF pointF = new PointF();
// valueAnimator.setEvaluator(new ArgbEvaluator());//颜色估值器
valueAnimator.setEvaluator(new TypeEvaluator<PointF>() {
/**
*
* @param fraction 执行的百分比
* @param startValue
* @param endValue
* @return
*/
@Override
public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
//evaluate 估值计算方法--可以在执行的过程当中干预改变属性的值---做效果:用自己的算法来控制
//不断的计算修改坐标
//X 坐标匀速运动 x = vt; 为了看起来效果好让t变成fraction*5
pointF.x = 100f * (fraction * 5);
//y 坐标是根据重力加速度公式来计算 加速度 y = vt = 1/2*g*t*t;
// pointF.y = 0.5f * 9.8f * (fraction * 5) * (fraction * 5);
pointF.y = 10f * 0.5f * 9.8f * (fraction * 5) * (fraction * 5);//Y 做大一点
return pointF;
}
});
//设置监听
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//为什么可以从 animation 里面 取到pointf 因为 setObjectValues 约束 和在估值器中 也设置了约束<PointF>
PointF f = (PointF) animation.getAnimatedValue();
ivTest.setX(f.x);
ivTest.setY(f.y);
}
});
valueAnimator.start();
}
动画8 插值器的使用
对应代码
/**
* 插值器 加速器 使用 setInterpolator
*/
public void startAnimator8() {
ObjectAnimator animator = ObjectAnimator.ofFloat(ivTest, "translationY", 0f, 1000f);
animator.setDuration(500);
// Interpolator interpolator = new Interpolator()
// animator.setInterpolator(new AccelerateInterpolator(1));//加速度
// animator.setInterpolator(new AccelerateDecelerateInterpolator());//先快后慢
animator.setInterpolator(new BounceInterpolator());//一个内插器,它的变化在末端反弹。
// animator.setInterpolator(new AnticipateInterpolator());//一个内插器,在那里,变化开始向后,然后向前移动。
// animator.setInterpolator(new CycleInterpolator(5));//往返运动
animator.start();
}
AccelerateDecelerateInterpolator 在动画开始与介绍的地方速率改变比较慢,在中间的时候加速
AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
AnticipateInterpolator 开始的时候向后然后向前甩
AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
BounceInterpolator 动画结束的时候弹起
CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
DecelerateInterpolator 在动画开始的地方快然后慢
LinearInterpolator 以常量速率改变
OvershootInterpolator 向前甩一定值后再回到原来位置