androidanimator
3.0以前,android⽀持两种动画模式,tween animation,frame animation,在android3.0中⼜引⼊了⼀个新的动画系统:property animation,这三种动画模式在SDK中被称为property animation,view animation,drawable animation。可通过项⽬在3.0之前的系统中使⽤Property Animation
1. View Animation(Tween Animation)
View Animation(Tween Animation):补间动画,给出两个关键帧,通过⼀些算法将给定属性值在给定的时间内在两个关键帧间渐变。kambara
View animation只能应⽤于View对象,⽽且只⽀持⼀部分属性,如⽀持缩放旋转⽽不⽀持背景颜⾊的改变。
mae west ⽽且对于View animation,它只是改变了View对象绘制的位置,⽽没有改变View对象本⾝,⽐如,你有⼀个Button,坐标
(100,100),Width:200,Height:50,⽽你有⼀个动画使其变为Width:100,Height:100,你会发现动画过程中触发按钮点击的区域仍是(100,100)-(300,150)。
View Animation就是⼀系列View形状的变换,如⼤⼩的缩放,透明度的改变,位置的改变,动画的定义既可以⽤代码定义也可以⽤XML定义,当然,建议⽤XML定义。
可以给⼀个View同时设置多个动画,⽐如从透明⾄不透明的淡⼊效果,与从⼩到⼤的放⼤效果,这些动画可以同时进⾏,也可以在⼀个完成之后开始另⼀个。
⽤XML定义的动画放在/res/anim/⽂件夹内,XML⽂件的根元素可以为<alpha>,<scale>,<translate>,<rotate>,interpolator元素或<t>(表⽰以上⼏个动画的集合,t可以嵌套)。默认情况下,所有动画是同时进⾏的,可以通过startOfft属性设置各个动画的开始偏移(开始时间)来达到动画顺序播放的效果。
可以通过设置interpolator属性改变动画渐变的⽅式,如AccelerateInterpolator,开始时慢,然后逐渐加快。默认为AccelerateDecelerateInterpolator。
定义好动画的XML⽂件后,可以通过类似下⾯的代码对指定View应⽤动画。
ImageView spaceshipImage = (ImageView)findViewById(R.id.spaceshipImage);
Animation hyperspaceJumpAnimation=AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
spaceshipImage.startAnimation(hyperspaceJumpAnimation);
2. Drawable Animation(Frame Animation)
Drawable Animation(Frame Animation):帧动画,就像GIF图⽚,通过⼀系列Drawable依次显⽰来模拟动画的效果。在XML中的定义⽅式如下:
<animation-list xmlns:android="/apk/res/android"
android:oneshot="true">
<item android:drawable="@drawable/rocket_thrust1" android:duration="200" />
<item android:drawable="@drawable/rocket_thrust2" android:duration="200" />
<item android:drawable="@drawable/rocket_thrust3" android:duration="200" />
</animation-list>
必须以<animation-list>为根元素,以<item>表⽰要轮换显⽰的图⽚,duration属性表⽰各项显⽰的时间。XML⽂件要放在/res/drawable/⽬录下。⽰例:
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
tContentView(R.layout.main);
imageView = (ImageView) findViewById(R.id.imageView1);
imageView.tBackgroundResource(R.drawable.drawable_anim);
anim = (AnimationDrawable) Background();
}
public boolean onTouchEvent(MotionEvent event) {
if (Action() == MotionEvent.ACTION_DOWN) {
anim.stop();
anim.start();
return true;
}
TouchEvent(event);
}
我在实验中遇到两点问题:
1. 要在代码中调⽤Imageview的tBackgroundResource⽅法,如果直接在XML布局⽂件中设置其src属性当触发动画时会FC。
2. 在动画start()之前要先stop(),不然在第⼀次动画之后会停在最后⼀帧,这样动画就只会触发⼀次。
puritan3. 最后⼀点是SDK中提到的,不要在onCreate中调⽤start,因为AnimationDrawable还没有完全跟Window相关联,如果想要界⾯显⽰时
就开始动画的话,可以在onWindowFoucsChanged()中调⽤start()。
3. Property Animation
属性动画,这个是在Android 3.0中才引进的,以前学WPF时⾥⾯的动画机制好像就是这个,它更改的是对象的实际属性,在View 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:重复次数与⽅式,如播放3次、5次、⽆限循环,可以此动画⼀直重复,或播放完时再反向播放
Animation ts:动画集合,即可以同时对⼀个对象应⽤⼏个动画,这些动画可以同时播放也可以对不同动画设置不同开始偏移Frame refreash delay:多少时间刷新⼀次,即每隔多少时间计算⼀次属性值,默认为10ms,最终刷新时间还受系统进程调度与硬件的影响
3.1 Property Animation的⼯作⽅式
对于下图的动画,这个对象的X坐标在40ms内从0移动到40 pixel.按默认的10ms刷新⼀次,这个对象会移动4次,每次移动
40/4=10pixel。
也可以改变属性值的改变⽅法,即设置不同的interpolation,在下图中运动速度先逐渐增⼤再逐渐减⼩
下图显⽰了与上述动画相关的关键对象
ValueAnimator 表⽰⼀个动画,包含动画的开始值,结束值,持续时间等属性。
ValueAnimator封装了⼀个TimeInterpolator,TimeInterpolator定义了属性值在开始值与结束值之间的插值⽅法。
ValueAnimator还封装了⼀个TypeAnimator,根据开始、结束值与TimeIniterpolator计算得到的值计算出属性值。
ValueAnimator根据动画已进⾏的时间跟动画总时间(duration)的⽐计算出⼀个时间因⼦(0~1),然后根据TimeInterpolator计算出另⼀个因⼦,最后TypeAnimator通过这个因⼦计算出属性值,如上例中10ms时:
⾸先计算出时间因⼦,即经过的时间百分⽐:t=10ms/40ms=0.25
经插值计算(inteplator)后的插值因⼦:⼤约为0.15,上述例⼦中⽤了AccelerateDecelerateInterpolator,计算公式为(input即为时间因⼦):(s((input + 1) * Math.PI) / 2.0f) + 0.5f;
最后根据TypeEvaluator计算出在10ms时的属性值:0.15*(40-0)=6pixel。上例中TypeEvaluator为FloatEvaluator,计算⽅法为:
public Float evaluate(float fraction, Number startValue, Number endValue) {
float startFloat = startValue.floatValue();
超强记忆力训练return startFloat + fraction * (endValue.floatValue() - startFloat);
return startFloat + fraction * (endValue.floatValue() - startFloat);
}
参数分别为上⼀步的插值因⼦,开始值与结束值。
3.2 ValueAnimator
ValueAnimator包含Property Animation动画的所有核⼼功能,如动画时间,开始、结束属性值,相应时间属性值计算⽅法等。应⽤
Property Animation有两个步聚:
1. 计算属性值
2. 根据属性值执⾏相应的动作,如改变对象的某⼀属性。
ValuAnimiator只完成了第⼀步⼯作,如果要完成第⼆步,需要实现UpdateListener接⼝,这个接⼝只有⼀个函数onAnimationUpdate(),在这个函数中会传⼊ValueAnimator对象做为参数,通过这个ValueAnimator对象的getAnimatedValue()函数可以得
到当前的属性值如:
大连日语培训学校ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.tDuration(1000);
animation.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {wyman
Log.i("update", ((Float) AnimatedValue()).toString());
}
});
animation.tInterpolator(new CycleInterpolator(3));
animation.start();
此⽰例中只是向Logcat输出了⼀些信息,可以改为想做的⼯作。
Animator.AnimatorListener
onAnimationStart()
onAnimationEnd()
onAnimationRepeat()
//当动画被取消时调⽤,同时会调⽤onAnimationEnd().
onAnimationCancel()
ValueAnimator.AnimatorUpdateListener
Value
可以继承AnimatorListenerAdapter⽽不是实现AnimatorListener接⼝来简化操作,这个类对Animator
Listener中的函数都定义了⼀个空函
数体,这样我们就只⽤定义想监听的事件⽽不⽤实现每个函数却只定义⼀空函数体。
ObjectAnimator oa=ObjectAnimator.ofFloat(tv, "alpha", 0f, 1f);
oa.tDuration(3000);
oa.addListener(new AnimatorListenerAdapter(){
public void on AnimationEnd(Animator animation){
Log.i("Animation","end");
}
});
oa.start();
3.3 ObjectAnimator
继承⾃ValueAnimator,要指定⼀个对象及该对象的⼀个属性,当属性值计算完成时⾃动设置为该对象的相应属性,即完成了Property Animation的全部两步操作。实际应⽤中⼀般都会⽤ObjectAnimator来改变某⼀对象的某⼀属性,但⽤ObjectAnimator有⼀定的限制,要想使
Animation的全部两步操作。实际应⽤中⼀般都会⽤ObjectAnimator来改变某⼀对象的某⼀属性,但⽤ObjectAnimator有⼀定的限制,要想使⽤ObjectAnimator,应该满⾜以下条件:
对象应该有⼀个tter函数:t<PropertyName>(驼峰命名法)
如上⾯的例⼦中,像ofFloat之类的⼯场⽅法,第⼀个参数为对象名,第⼆个为属性名,后⾯的参数为可变参数,如果values…参数只设置了⼀个值的话,那么会假定为⽬的值,属性值的变化范围为当前值到⽬的值,为了获得当前值,该对象要有相应属性的getter⽅法:get<PropertyName>
如果有getter⽅法,其应返回值类型应与相应的tter⽅法的参数类型⼀致。
如果上述条件不满⾜,则不能⽤ObjectAnimator,应⽤ValueAnimator代替。
tv=(TextView)findViewById(view1);
btn=(Button)findViewById(R.id.button1);
vampiro
btn.tOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
ObjectAnimator oa=ObjectAnimator.ofFloat(tv, "alpha", 0f, 1f);
oa.tDuration(3000);
oa.start();
}
});
把⼀个TextView的透明度在3秒内从0变⾄1。
根据应⽤动画的对象或属性的不同,可能需要在onAnimationUpdate函数中调⽤invalidate()函数刷新视图。
3.4 通过AnimationSet应⽤多个动画
AnimationSet提供了⼀个把多个动画组合成⼀个组合的机制,并可设置组中动画的时序关系,如同时播放,顺序播放等。
以下例⼦同时应⽤5个动画:
1. 播放anim1;
2. 同时播放anim2,anim3,anim4;
3. 播放anim5。
AnimatorSet bouncer = new AnimatorSet();
bouncer.play(anim1).before(anim2);
bouncer.play(anim2).with(anim3);
bouncer.play(anim2).with(anim4)
bouncer.play(anim5).after(amin2);
animatorSet.start();
误判3.5 TypeEvalutors
根据属性的开始、结束值与TimeInterpolation计算出的因⼦计算出当前时间的属性值,android提供了以下⼏个evalutor:
IntEvaluator:属性的值类型为int;
FloatEvaluator:属性的值类型为float;
ArgbEvaluator:属性的值类型为⼗六进制颜⾊值;
TypeEvaluator:⼀个接⼝,可以通过实现该接⼝⾃定义Evaluator。frisian
⾃定义TypeEvalutor很简单,只需要实现⼀个⽅法,如FloatEvalutor的定义:
public class FloatEvaluator implements TypeEvaluator {
public Object evaluate(float fraction, Object startValue, Object endValue) {
float startFloat = ((Number) startValue).floatValue();
圣诞歌曲有哪些
return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
}
}
根据动画执⾏的时间跟应⽤的Interplator,会计算出⼀个0~1之间的因⼦,即evalute函数中的fraction参数,通过上述FloatEvaluator应该很好看出其意思。
很好看出其意思。
3.6 TimeInterplator
Time interplator定义了属性值变化的⽅式,如线性均匀改变,开始慢然后逐渐快等。在Property Animation中是TimeInterplator,在View Animation中是Interplator,这两个是⼀样的,在3.0之前只有Interplator,3.0之后实现代码转移⾄了TimeInterplator。Interplator继承⾃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,以上⼏个都是实现了这个接⼝
3.7 当Layout改变时应⽤动画
ViewGroup中的⼦元素可以通过tVisibility使其Visible、Invisible或Gone,当有⼦元素可见性改变时(VISIBLE、GONE),可以向其应⽤动画,通过LayoutTransition类应⽤此类动画:
transition.tAnimator(LayoutTransition.DISAPPEARING, customDisappearingAnim);
通过tAnimator应⽤动画,第⼀个参数表⽰应⽤的情境,可以以下4种类型:
APPEARING 当⼀个元素在其⽗元素中变为Visible时对这个元素应⽤动画
CHANGE_APPEARING 当⼀个元素在其⽗元素中变为Visible时,因系统要重新布局有⼀些元素需要移动,对这些要移动的元素应⽤动画
DISAPPEARING 当⼀个元素在其⽗元素中变为GONE时对其应⽤动画
CHANGE_DISAPPEARING 当⼀个元素在其⽗元素中变为GONE时,因系统要重新布局有⼀些元素需要移动,这些要移动的元素应⽤动画.
第⼆个参数为⼀Animator。
mTransitioner.tStagger(LayoutTransition.CHANGE_APPEARING, 30);
此函数设置动画延迟时间,参数分别为类型与时间。
3.8 Keyframes
keyFrame是⼀个时间/值对,通过它可以定义⼀个在特定时间的特定状态,即关键帧,⽽且在两个keyFrame之间可以定义不同的Interpolator,就好像多个动画的拼接,第⼀个动画的结束点是第⼆个动
画的开始点。KeyFrame是抽象类,要通过ofInt(),ofFloat(),ofObject()获得适当的KeyFrame,然后通过PropertyValuesHolder.ofKeyframe获得PropertyValuesHolder对象,如以下例⼦:
Keyframe kf0 = Keyframe.ofInt(0, 400);
Keyframe kf1 = Keyframe.ofInt(0.25f, 200);
Keyframe kf2 = Keyframe.ofInt(0.5f, 400);
Keyframe kf4 = Keyframe.ofInt(0.75f, 100);
Keyframe kf3 = Keyframe.ofInt(1f, 500);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2, kf4, kf3);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(btn2, pvhRotation);
rotationAnim.tDuration(2000);
上述代码的意思为:设置btn对象的width属性值使其:
开始时 Width=400