一. Property Animation产生的背景:
由于Tween Animation(补间动画)只能实现简单的四种的动画(alpha、scale、rotate、translate),要想实现比较复杂的动画就难以满足需求,而且补间动画只是改变了View对象绘制的位置,而没有改变View对象本身,比如View形状的变换,如大小的缩放,透明度的改变,位置的改变,其实本身并没有改变,举个例子就好比孙悟空灵魂出窍一样,虽然已经上天入地,其实肉体还在那里一动不动,我们开发过程中的经常遇见的就是translate之后事件还在原地。如果要实现既要有动画效果又要使得View本身得到真正改变,那就要借助属性动画了,这也是属性动画引入的原因。它能够更加灵活的实现各种效果,不仅限于类似补间动画实现的哪几种效果。
(1)Property Animation相关类
属性动画,根据字面理解可以通过修改物件的属性值以达到动画效果。
类名 | 用途 |
ValueAnimator | 属性动画主要的计时器,也计算动画后的属性的值,动画的执行类 |
ObjectAnimator | ValueAnimator的一个子类,允许你设置一个目标对象和对象的属性进行动画,动画的执行类 |
AnimatorSet | 提供组织动画的结构,使它们能相关联得运行,用于控制一组动画的执行 |
AnimatorInflater | 用户加载属性动画的xml文件 |
Evaluators | 属性动画计算器,告诉了属性动画系统如何计算给出属性的值 |
Interpolators | 动画插入器,定义动画的变化率 |
(2)Interpolator(插值器)
Interpolator插值器用于控制动画的变化速率,也可以简单的理解成用于控制动画的快慢,插值器目前都只是对动画执行过程的时间进行修饰,并没有对轨迹进行修饰。系统提供的插值器有以下几种:
插值器名字 | 解说 | 对应的xml |
AccelerateInterpolator | 加速,开始时慢中间加速 | @android:anim/accelerate_interpolator |
DecelerateInterpolator | 减速,开始时快然后减速 | @android:anim/decelerate_interpolator |
AccelerateDecelerateInterolator | 先加速后减速,开始结束时慢,中间加速 | @android:anim/accelerate_decelerate_interpolator |
AnticipateInterpolator | 反向 ,先向相反方向改变一段再加速播放 | @android:anim/anticipate_interpolator |
AnticipateOvershootInterpolator | 反向加超越,先向相反方向改变,再加速播放,会超出目的值然后缓慢移动至目的值 | @android:anim/anticipate_overshoot_interpolator |
BounceInterpolator | 跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100 | @android:anim/bounce_interpolator |
CycleIinterpolator | 循环,动画循环一定次数,值的改变为一正弦函数:Math.sin(2* mCycles* Math.PI* input) | @android:anim/cycle_interpolator |
LinearInterpolator | 线性,线性均匀改变 | @android:anim/linear_interpolator |
OvershootInterpolator | 超越,最后超出目的值然后缓慢改变到目的值 | @android:anim/overshoot_interpolator |
二. 使用ObjectAnimator
(1)alpha渐变效果
1>java代码实现
ObjectAnimator animator = ObjectAnimator.ofFloat(image, "alpha", 1.0f, 0.1f); //绑定布局,设置为渐变,从1.0 --> 0.1 animator.setDuration(2000); //设置动画时间 animator.setRepeatCount(10); //设置动画显示次数 animator.setRepeatMode(ValueAnimator.REVERSE); //设置动画显示模式,反向 animator.setStartDelay(200); //设置动画多次显示的时间间隔 animator.setInterpolator(new OvershootInterpolator()); //设置动画插入器,插入器直接影响显示结果 animator.start(); //开始动画
2>xml实现
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:propertyName="alpha" android:duration="3000" android:repeatCount="1" android:repeatMode="reverse" android:startOffset="200" android:valueFrom="1.0" android:valueTo="0.1" android:valueType="floatType"> </objectAnimator>
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.object1_layout); animator.setTarget(image); animator.start();
(2)scale翻转效果(与补间动画scale有些区别)
1>java代码实现
ObjectAnimator animator = ObjectAnimator .ofFloat(image, "scaleX", 1.0f, 0.1f); //scaleX为Y轴不变,以view中心为点,X轴翻转;scaleY效果相反 animator.setDuration(2000); animator.setRepeatCount(10); animator.setRepeatMode(ValueAnimator.REVERSE); animator.setStartDelay(200); animator.setInterpolator(new OvershootInterpolator()); animator.start();
2>xml实现
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:propertyName="scaleX" android:repeatCount="10" android:repeatMode="restart" android:valueFrom="1.0" android:valueTo="0.1" android:duration="2000" android:startOffset="200" android:valueType="floatType"> </objectAnimator>
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.object1_layout); animator.setTarget(image); animator.start();
(3)rotation 旋转效果(与补间动画rotate书写不一样)
1>java代码实现
ObjectAnimator animator = ObjectAnimator.ofFloat(image, "rotation", 0f, 360f); //旋转角度0 --> 360 animator.setDuration(2000); animator.setRepeatCount(10); animator.setRepeatMode(ValueAnimator.REVERSE); animator.setStartDelay(200); animator.setInterpolator(new OvershootInterpolator()); animator.start();
2>xml实现
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:propertyName="rotation" android:repeatCount="10" android:repeatMode="restart" android:valueFrom="0f" android:valueTo="360f" android:duration="2000" android:startOffset="200" android:valueType="floatType"> </objectAnimator>
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.object1_layout); animator.setTarget(image); animator.start();
(4)translation(与补间动画translate书写不一样)
1>java代码实现
//translationX,Y轴不变,水平X轴移动,0f为屏幕中心,0f --> 480f(水平向右移动);translationY,X轴不变,水平Y轴移动 ObjectAnimator animator = ObjectAnimator.ofFloat(image, "translationX", 0f, 480f); animator.setDuration(2000); animator.setRepeatCount(10); animator.setRepeatMode(ValueAnimator.REVERSE); animator.setStartDelay(200); animator.setInterpolator(new OvershootInterpolator()); animator.start();
2>xml实现
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:propertyName="translationY" android:repeatCount="10" android:repeatMode="restart" android:valueFrom="0f" android:valueTo="480f" android:duration="2000" android:startOffset="200" android:valueType="floatType"> </objectAnimator>
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.object1_layout); animator.setTarget(image); animator.start();
(5)set
1>java代码实现(旋转向右移动)
①使用AnimatroSet实现
AnimatorSet animatorSet = new AnimatorSet(); ObjectAnimator animator = ObjectAnimator.ofFloat(image, "translationX", 0f, 400f); animator.setRepeatMode(ValueAnimator.REVERSE); //动画模式,需要单独设置 animator.setRepeatCount(10); //动画次数n+1次,需要单独设置 ObjectAnimator animator1 = ObjectAnimator.ofFloat(image, "rotation", 0f, 360f); animator1.setRepeatMode(ValueAnimator.REVERSE); //动画模式,需要单独设置 animator1.setRepeatCount(10); //动画次数n+1次,需要单独设置 animatorSet.setDuration(2000); //动画时间,可set设置 animatorSet.setStartDelay(200); //动画间隔,可set设置 animatorSet.playTogether(animator,animator1); //set添加动画 animatorSet.setInterpolator(new OvershootInterpolator()); animatorSet.start();
②使用PropertyValuesHolder实现
PropertyValuesHolder scaleXValuesHolder = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0.1f); PropertyValuesHolder scaleYValuesHolder = PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.1f); ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(image, scaleXValuesHolder, scaleYValuesHolder); objectAnimator.setDuration(2000); objectAnimator.setRepeatCount(10); objectAnimator.setRepeatMode(ValueAnimator.REVERSE); objectAnimator.start();
③使用ViewPropertyAnimator实现
ViewPropertyAnimator viewPropertyAnimator=image.animate(); viewPropertyAnimator.scaleXBy(1.0f).scaleX(0.1f).alphaBy(1.0f).scaleY(0.1f).setDuration(2000).start();
2>xml实现
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:duration="2000" android:propertyName="translationX" android:repeatCount="10" android:repeatMode="reverse" android:startOffset="200" android:valueFrom="0f" android:valueTo="400f" android:valueType="floatType" /> <objectAnimator android:duration="2000" android:propertyName="rotation" android:repeatCount="10" android:repeatMode="reverse" android:startOffset="200" android:valueFrom="0f" android:valueTo="360f" android:valueType="floatType" /> </set>
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.object1_layout); animator.setTarget(image); animator.start();
三. ObjectAnimator的监听事件
(1)ObjectAnimator.addListener
有时候我们可能要在某一个动画执行之前 或者动画结束之后进行一些其他的操作
ObjectAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { //TODO 动画开始前的操作 Log.i("aaaaa", "动画开始前的操作"); } @Override public void onAnimationEnd(Animator animator) { //TODO 动画结束的操作 Log.i("aaaaa", "动画结束的操作"); } @Override public void onAnimationCancel(Animator animator) { //TODO 动画取消的操作 Log.i("aaaaa", "动画取消的操作"); } @Override public void onAnimationRepeat(Animator animator) { //TODO 动画重复的操作 Log.i("aaaaa", "动画重复的操作"); } });
(2)objectAnimator.addUpdateListener
如果我们需要简单动画执行过程中的变化可以使用AnimatorUpdateListener
ObjectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { float value = (float) animator.getAnimatedValue(); Log.i("aaaaa", "valueAnimator : " + value); if (value >= 300 && value <= 320) Toast.makeText(AnimatorActivity.this, value + "", Toast.LENGTH_SHORT).show(); } });
四. ValueAnimator(差值动画)
ValueAnimator是ObjectAnimator的父类,它继承自抽象类Animator,它作用于一个值,将其由一个值变化为另外一个值,然后根据值的变化,按照一定的规则,动态修改View的属性,比如View的位置、透明度、旋转角度、大小等,即可完成了动画的效果。
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 12164f); valueAnimator.setDuration(5000); valueAnimator.setInterpolator(new LinearInterpolator()); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { float money = (float) valueAnimator.getAnimatedValue(); textView.setText(String.format("%.2f", money)); } }); valueAnimator.start();
每天进步一点点!