动画(2)——属性动画
Property Animation(属性动画)
在View Animation(Tween Animation)中,其改变的是View的绘制效果,真正的View的属性保持不变,而在Property Animation中,改变的是对象的实际属性
<1>、属性动画与补间动画的不同点
<2>、属性动画与补间动画的相同点
<3>、ValuAnimiator
1)、ValuAnimiator仅仅是计算动画过程中变化的值,并没有把这些计算出来的值应用到任何对象或属性上,因此光是创建ValuAnimiator对象并不会显示任何动画,所以需要为动画实现ValueAnimator.onUpdateListener接口,这个接口只有一个函数onAnimationUpdate(),在这个函数中会传入做为参数,通过这个ValueAnimator对象的getAnimatedValue()函数可以得到当前帧的属性值,并将算出来的值应用到指定对象上。还可以为ValueAnimator对象设置指定的计算器接口(通过实现TypeEvaluator)
2)、具体步骤
例如:
又如:
3)、Evaluator
常用的有:
注意:自定义TypeEvaluator时,fraction为当前帧时刻除以duration。
4)、优点
不需要操作的对象的属性一定要有getter和setter方法,可以自己根据当前动画的计算值,来操作任何属性,可以自定义中间帧时各个属性值计算方式(typeEvaluator),灵活性强。
<4>、ObjectAnimator
1)、概述
如:
2)、与valueAnimator的不同之处
2)、常用属性值
关于View在3.0之后引入的几个新的属性,并设置了其getter和setter方法:
3.1)translationX 和 translationY:这两个属性控制了View所处的位置,它们的值是由layout容器设置的,是相对于坐标原点(0,0左上角)的一个偏移量。
3.2)rotation, rotationX 和 rotationY:控制View绕着轴点(pivotX和pivotY)旋转。rotationX、Y 旋转,是立体的旋转,默认是以View的中心点
3.3)scaleX 和 scaleY:控制View基于pivotX和pivotY的缩放。
3.4)pivotX 和 pivotY:旋转的轴点和缩放的基准点,默认是View的中心点。
3.5)x 和 y:描述了view在其父容器中的最终位置,是左上角左标和偏移量(translationX,translationY)的和。
3.6)aplha:透明度,1是完全不透明,0是完全透明。
注意:跟位置有关的参数有3个,以X坐标为例,可以通过getLeft(),getX(),getTranslateX()获得。无论怎样应用动画,原来的布局时的位置通过getLeft()获得,保持不变;getX是View最终的位置;gettranslationX为最终位置与布局时初始位置这差,所以getX()的值为getLeft()与getTranslationX()的和。
3)、使用步骤和动画集
在XML中定义ObjectAnimator
在代码中,利用AnimationInflater类的loadAnimator方法来获取我们的ObjectAnimator对象,利用setTarget(View)方法来设置这个动画应用的对象,触发动画效果,就是调用其start方法了:
也可定义ObjectAnimator动画集:
代码中:
也可在代码中直接通过 AnimatorSet的playTogether方法或者playAfter, playBefore等方法将其加入到set中,给set设置相对应的如duration之类的属性,我们还能够给Animator添加一个Listener,让它能够对Animator的几个关键点进行响应,分别是开始,结束,重复,取消时的响应函数。
关于动画集的播放顺序:
先播放anim1,再同时播放anim2,anim3,anim4,最后播放anim5。
注意:Property Animation也可以在XML中定义:<set> - AnimatorSet、<animator> - ValueAnimator、<objectAnimator> - ObjectAnimator
2)、动画监听器
5.1)、 AnimatorListener
监听动画的开始、结束、被取消、重复等事件,animator还有cancel()和end()方法:cancel动画立即停止,停在当前的位置;end动画直接到最终状态。
5.2)、AnimatorListenerAdapter
可以继承AnimatorListenerAdapter而不是实现AnimatorListener接口来简化操作,这个类对AnimatorListener中的函数都定义了一个空函数体,这样我们就只用定义想监听的事件而不用实现每个函数却只定义一空函数体。
2)、PropertyValuesHolder
6.1)、通过 PropertyValuesHolder类的工厂方法ofInt, ofFloat等方法,让它能够Hold住对应property的value,再利用ObjectAnimator的ofPropertyValuesHolder方法时,再将我们上面定义的propertyValuesHolder给传进去,定义出一个objectAnimator。设置objectAnimator对应的属性,调用其Start方法就行。
6.2)、添加keyframe
keyFrame是一个 时间/值 对,通过它可以定义一个在特定时间的特定状态,即关键帧,而且在两个keyFrame之间可以定义不同的Interpolator,就好像多个动画的拼接,第一个动画的结束点是第二个动画的开始点。KeyFrame是抽象类,要通过ofInt(),ofFloat(),ofObject()获得适当的KeyFrame,然后通过PropertyValuesHolder.ofKeyframe获得PropertyValuesHolder对象,例如:
上述代码的意思为:设置btn对象的width属性值使其:开始时 Width=400,动画开始1/4时 Width=200,动画开始1/2时 Width=400,动画开始3/4时 Width=100,动画结束时 Width=500。第一个参数为时间百分比,第二个参数是在第一个参数的时间时的属性值。定义了一些Keyframe后,通过PropertyValuesHolder类的方法ofKeyframe一个PropertyValuesHolder对象,然后通过ObjectAnimator.ofPropertyValuesHolder获得一个Animator对象。
用下面的代码可以实现同样的效果(上述代码时间值是线性,变化均匀)
<5>、ViewPropertyAnimator类
通过view.animate()来获取ViewPropertyAnimator。该类能直接操作多个属性的动画,该类对多属性动画进行了优化,会合并一些invalidate()来减少刷新视图,该类在3.1中引入。