android控件的动画分为三种:property animation,tween animation,frame animation,这三种动画模式在SDK中被称为property animation,view animation,drawable animation。
补间动画,给出两个关键帧,通过一些算法将给定属性值在给定的时间内在两个关键帧间渐变。
它只是改变了View对象的绘制,而没有改变View对象本身.
分为以下四种动画:
① AlphaAnimation
渐变动画,主要控制透明度变化动画类,常使用AlphaAnimation(float fromAlpha, float toAlpha)来构造;
fromAlpha:动画开始时的透明度(取值范围为0.0到1.0);
toAlpha:动画结束时的透明度;
duration:持续时间(单位:毫秒)
② ScaleAnimation
主要控制尺度变化的动画类,常使用ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)来构造;
fromX:动画开始X坐标上的伸缩尺度;
toX:动画结束X坐标上的伸缩尺度;
fromY:动画开始Y坐标上的伸缩尺度;
toY:动画结束Y坐标上的伸缩尺度;
pivotXType:X坐标上的伸缩模式,取值有:Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, Animation.RELATIVE_TO_PARENT;
pivotXValue:X坐标上的伸缩值;
pivotYType:Y坐标上的伸缩模式,取值有:Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, Animation.RELATIVE_TO_PARENT;
pivotYValue:Y坐标上的伸缩值;
duration:持续时间(单位:毫秒)
③ TranslateAnimation
主要控制位置变换的动画实现类,常使用TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)来构造;
fromXDelta:动画开始的X坐标;
toXDelta:动画结束的X坐标;
fromYDelta:动画开始的Y坐标;
toYDelta:动画结束的Y坐标;
duration:持续时间(单位:毫秒)
④ RotateAnimation
主要控制旋转的动画实现类,常使用RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)来构造;
fromDegrees:旋转开始角度;
toDegrees:旋转结束角度;
pivotXType, pivotXValue, pivotYType, pivotYValue与尺度变化动画ScaleAnimation类似;
duration:持续时间(单位:毫秒)
注意:
1. 没有指定, 默认是以自己为相对参照物。
在这些属性里面还可以加上%和p,例如:
android:toXDelta="100%",表示自身的100%,也就是从View自己的位置开始。
android:toXDelta="80%p",表示父层View的80%,是以它父层View为参照的。
还可以是绝对的单位
2. 默认情况下,所有动画是同时进行的,可以通过startOffset属性设置各个动画的开始偏移(开始时间,单位:毫秒)来达到动画顺序播放的效果。
3. 可以通过设置interpolator属性改变动画渐变的方式,如AccelerateInterpolator,开始时慢,然后逐渐加快。默认为AccelerateDecelerateInterpolator。
接下来讲一讲translate的几个重要的属性:
android:interpolator: 加速器,非常有用的属性,可以简单理解为动画的速度,可以是越来越快,也可以是越来越慢,
或者是先快后忙,或者是均匀的速度等等,对于值如下:
- @android:anim/accelerate_interpolator: 越来越快
- @android:anim/decelerate_interpolator:越来越慢
- @android:anim/accelerate_decelerate_interpolator:先快后慢
- @android:anim/anticipate_interpolator: 先后退一小步然后向前加速
- @android:anim/overshoot_interpolator:快速到达终点超出一小步然后回到终点
- @android:anim/anticipate_overshoot_interpolator:到达终点超出一小步然后回到终点
- @android:anim/bounce_interpolator:到达终点产生弹球效果,弹几下回到终点
- @android:anim/linear_interpolator:均匀速度。
定义好动画的XML文件后,可以通过类似下面的代码对指定View应用动画。
ImageView spaceshipImage = (ImageView)findViewById(R.id.spaceshipImage);
Animation hyperspaceJumpAnimation=AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
spaceshipImage.startAnimation(hyperspaceJumpAnimation);
Ⅱ: Drawable Animation(Frame Animation)
Drawable Animation(Frame Animation):帧动画,就像GIF图片,通过一系列Drawable依次显示来模拟动画的效果。通过给控件设置setBackgroundResource实现,在XML中的定义方式如下:<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true"> //是否只播放一次
<item android:drawable="@drawable/1" android:duration="200" />
<item android:drawable="@drawable/2" android:duration="200" />
<item android:drawable="@drawable/t3" android:duration="200" />
</animation-list>
//必须以<animation-list>为根元素,以<item>表示要轮换显示的图片,duration属性表示各项显示的时间。XML文件要放在/res/drawable/目录下
imageView = (ImageView) findViewById(R.id.imageView);
imageView.setBackgroundResource(R.drawable.drawable_anim);
anim = (AnimationDrawable) imageView.getBackground();
anim.start();
Ⅲ: Property Animation
属性动画,它更改的是对象的实际属性,在Tween Animation,其改变的是View的绘制效果,真正的View的属性保持不变,比如无论你在对话中如何缩放Button的大小,Button的有效点击区域还是没有应用动画时的区域,其位置与大小都不变。而在Property Animation中,改变的是对象的实际属性,如Button的缩放,Button的位置与大小属性值都改变了。而且Property Animation不止可以应用于View,还可以应用于任何对象。Property Animation只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的.
在Property Animation中,可以对动画应用以下属性:
Duration:动画的持续时间
TimeInterpolation:插值器
TypeEvaluator:计算方式,根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值
Repeat Count and behavoir:重复次数与方式
Animation sets:动画集合,即可以同时对一个对象应用几个动画,这些动画可以同时播放也可以对不同动画设置不同开始偏移
Frame refreash delay:多少时间刷新一次,即每隔多少时间计算一次属性值,默认为10ms,最终刷新时间还受系统进程调度与硬件的影响。
Property Animation的工作方式
ValueAnimator 表示一个动画,包含动画的开始值,结束值,持续时间等属性。
ValueAnimator封装了一个TimeInterpolator,TimeInterpolator定义了属性值在开始值与结束值之间的插值方法。
ValueAnimator还封装了一个TypeAnimator,根据开始、结束值与TimeIniterpolator计算得到的值计算出属性值。
ValueAnimator根据动画已进行的时间跟动画总时间(duration)的比计算出一个客观时间比例(0~1),然后根据TimeInterpolator计算出插值后的时间因子,最后TypeAnimator通过这个因子计算出属性值
对于ValueAnimator有两种监听
Animator.AnimatorListener(可通过继承AnimatorListenerAdapter简化操作,该抽象类为接口的空实现)
onAnimationStart()
onAnimationEnd()
onAnimationRepeat()
//当动画被取消时调用,同时会调用onAnimationEnd().
onAnimationCancel()
ValueAnimator.AnimatorUpdateListener
onAnimationUpdate() //通过监听这个事件在属性的值更新时执行相应的操作,对于ValueAnimator一般要监听此事件执行相应的动作,不然Animation没意义,在ObjectAnimator(继承自ValueAnimator)中会自动更新属性,如无必要不必监听。在函数中会传递一个ValueAnimator参数,通过此参数的getAnimatedValue()取得当前动画属性值。
ObjectAnimator
继承自ValueAnimator,要指定一个对象及该对象的一个属性,当属性值计算完成时自动设置为该对象的相应属性,即完成了Property Animation的全部两步操作。实际应用中一般都会用ObjectAnimator来改变某一对象的某一属性,但用ObjectAnimator有一定的限制,要想使用ObjectAnimator,应该满足以下条件:
对象应该有一个setter函数:set(驼峰命名法)
1 | tv=(TextView)findViewById(R.id.textview1); |
如上面的例子中,像ofFloat之类的工场方法,第一个参数为对象名,第二个为属性名,后面的参数为可变参数,如果values…参数只设置了一个值的话,那么会假定为目的值,属性值的变化范围为当前值到目的值,为了获得当前值,该对象要有相应属性的getter方法:get<PropertyName>
如果有getter方法,其应返回值类型应与相应的setter方法的参数类型一致。
如果上述条件不满足(即没有get方法和set方法),则不能用ObjectAnimator,应用ValueAnimator代替。根据应用动画的对象或属性的不同,可能需要在onAnimationUpdate函数中调用invalidate()函数刷新视图。
AnimationSet
AnimationSet提供了一个把多个动画组合成一个组合的机制,并可设置组中动画的时序关系,如同时播放,顺序播放等。
1 | AnimatorSet bouncer = new AnimatorSet(); |
TypeEvalutors
根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值,android提供了以下几个evalutor:
IntEvaluator:属性的值类型为int;
FloatEvaluator:属性的值类型为float;
ArgbEvaluator:属性的值类型为十六进制颜色值;
TypeEvaluator:一个接口,可以通过实现该接口自定义Evaluator。
自定义TypeEvalutor很简单,只需要实现一个方法,如FloatEvalutor的定义:
1 | public class FloatEvaluator implements TypeEvaluator { |
TimeInterplator
AccelerateInterpolator 加速,开始时慢中间加速
DecelerateInterpolator 减速,开始时快然后减速
AccelerateDecelerateInterolator 先加速后减速,开始结束时慢,中间加速
AnticipateInterpolator 反向 ,先向相反方向改变一段再加速播放
AnticipateOvershootInterpolator 反向加回弹,先向相反方向改变,再加速播放,会超出目的值然后缓慢移动至目的值
BounceInterpolator 跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100
CycleIinterpolator 循环,动画循环一定次数,值的改变为一正弦函数:Math.sin(2 * mCycles * Math.PI * input)
LinearInterpolator 线性,线性均匀改变
OvershottInterpolator 回弹,最后超出目的值然后缓慢改变到目的值
TimeInterpolator 一个接口,允许你自定义interpolator,以上几个都是实现了这个接口
LayoutTransition
Property animation系统还提供了对ViewGroup中的View改变加入动画的功能。当有子元素可见性改变时(VISIBLE、GONE),可以向其应用动画,通过LayoutTransition类应用此类动画:
container.setLayoutTransition(mTransitioner);
mTransitioner.setAnimator(LayoutTransition.DISAPPEARING, customDisappearingAnim);
通过setAnimator应用动画,第一个参数表示应用的情境,可以以下4种类型:
APPEARING 当一个元素在其父元素中变为Visible时对这个元素应用动画
CHANGE_APPEARING 当一个元素在其父元素中变为Visible时,因系统要重新布局有一些元素需要移动,对这些要移动的元素应用动画
DISAPPEARING 当一个元素在其父元素中变为GONE时对其应用动画
CHANGE_DISAPPEARING 当一个元素在其父元素中变为GONE时,因系统要重新布局有一些元素需要移动,这些要移动的元素应用动画.
第二个参数为一Animator。
mTransitioner.setStagger(LayoutTransition.CHANGE_APPEARING, 30);
此函数设置动画延迟时间,参数分别为类型与时间。
Keyframes
keyFrame是一个 时间/值 对,通过它可以定义一个在特定时间的特定状态,即关键帧,而且在两个keyFrame之间可以定义不同的Interpolator,就好像多个动画的拼接,第一个动画的结束点是第二个动画的开始点。KeyFrame是抽象类,要通过ofInt(),ofFloat(),ofObject()获得适当的KeyFrame,然后通过PropertyValuesHolder.ofKeyframe获得PropertyValuesHolder对象,如以下例子:
1 | Keyframe kf0 = Keyframe.ofInt(0, 400); |
上述代码的意思为:设置btn对象的width属性值使其:
开始时 Width=400
动画开始1/4时 Width=200
动画开始1/2时 Width=400
动画开始3/4时 Width=100
动画结束时 Width=500