Android动画学习笔记-Android Animation
3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中又引入了一个新的动画系统:property animation,这三种动画模式在SDK中被称为property animation,view animation,drawable animation。 可通过NineOldAndroids 项目在3.0之前的系统中使用Property Animation
1. ViewAnimation(Tween Animation)
View Animation(Tween Animation):补间动画,给出两个关键帧,通过一些算法将给定属性值在给定的时间内在两个关键帧间渐变。
View animation只能应用于View对象,而且只支持一部分属性,如支持缩放旋转而不支持背景颜色的改变。
而且对于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元素或<set>(表示以上几个动画的集合,set可以嵌套)。默认情况下,所有动画是同时进行的,可以通过startOffset属性设置各个动画的开始偏移(开始时间)来达到动画顺序播放的效果。
可以通过设置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中的定义方式如下:
1 2 3 4 5 6 | <animation-list xmlns:android="http://schemas.android.com/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
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imageView = (ImageView)findViewById(R.id.imageView1);
imageView.setBackgroundResource(R.drawable.drawable_anim);
anim = (AnimationDrawable)imageView.getBackground();
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() ==MotionEvent.ACTION_DOWN) {
anim.stop();
anim.start();
return true;
}
return super.onTouchEvent(event);
}
我在实验中遇到两点问题:
1. 要在代码中调用Imageview的setBackgroundResource方法,如果直接在XML布局文件中设置其src属性当触发动画时会FC。
2. 在动画start()之前要先stop(),不然在第一次动画之后会停在最后一帧,这样动画就只会触发一次。
3. 最后一点是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计算出的因子计算出当前时间的属性值
· RepeatCountry and behavoir:重复次数与方式,如播放3次、5次、无限循环,可以此动画一直重复,或播放完时再反向播放
· Animationsets:动画集合,即可以同时对一个对象应用几个动画,这些动画可以同时播放也可以对不同动画设置不同开始偏移
· Framerefreash delay:多少时间刷新一次,即每隔多少时间计算一次属性值,默认为10ms,最终刷新时间还受系统进程调度与硬件的影响
· 动画通过机器的性能自动计算Frame refreash delay刷新时间,在这个时间点上根据根据:动画的开始、结束值、持续时长与TimeInterpolation计算出的因子计算出当前时间的属性值TypeEvaluato,把时间点和该时间点上动画的属性状态进行显示,就形成了动画
3.1 PropertyAnimation的工作方式
对于下图的动画,这个对象的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即为时间因子):
(Math.cos((input + 1) *Math.PI) / 2.0f) + 0.5f;
最后根据TypeEvaluator计算出在10ms时的属性值:0.15*(40-0)=6pixel。上例中TypeEvaluator为FloatEvaluator,计算方法为 :
public Float evaluate(float fraction, NumberstartValue, Number endValue) {
float startFloat = startValue.floatValue();
return startFloat + fraction * (endValue.floatValue() -startFloat);
}
参数分别为上一步的插值因子,开始值与结束值。
3.2ValueAnimator
ValueAnimator包含Property Animation动画的所有核心功能,如动画时间,开始、结束属性值,相应时间属性值计算方法等。应用Property Animation有两个步聚:
1. 计算属性值
2. 根据属性值执行相应的动作,如改变对象的某一属性。
ValuAnimiator只完成了第一步工作,如果要完成第二步,需要实现ValueAnimator.onUpdateListener接口,这个接口只有一个函数onAnimationUpdate(),在这个函数中会传入ValueAnimator对象做为参数,通过这个ValueAnimator对象的getAnimatedValue()函数可以得到当前的属性值如:
ValueAnimator animation =ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.i("update",((Float) animation.getAnimatedValue()).toString());
}
});
animation.setInterpolator(new CycleInterpolator(3));
animation.start();
此示例中只是向Logcat输出了一些信息,可以改为想做的工作。
Animator.AnimatorListener
onAnimationStart()
onAnimationEnd()
onAnimationRepeat()
//当动画被取消时调用,同时会调用onAnimationEnd().
onAnimationCancel()
ValueAnimator.AnimatorUpdateListener
onAnimationUpdate() //通过监听这个事件在属性的值更新时执行相应的操作,对于ValueAnimator一般要监听此事件执行相应的动作,不然Animation没意义,在ObjectAnimator(继承自ValueAnimator)中会自动更新属性,如无必要不必监听。在函数中会传递一个ValueAnimator参数,通过此参数的getAnimatedValue()取得当前动画属性值。
可以继承AnimatorListenerAdapter而不是实现AnimatorListener接口来简化操作,这个类对AnimatorListener中的函数都定义了一个空函数体,这样我们就只用定义想监听的事件而不用实现每个函数却只定义一空函数体。
ObjectAnimatoroa=ObjectAnimator.ofFloat(tv, "alpha", 0f, 1f);
oa.setDuration(3000);
oa.addListener(newAnimatorListenerAdapter(){
public void on AnimationEnd(Animator animation){
Log.i("Animation","end");
}
});
oa.start();
3.3ObjectAnimator
继承自ValueAnimator,要指定一个对象及该对象的一个属性,当属性值计算完成时自动设置为该对象的相应属性,即完成了Property Animation的全部两步操作。实际应用中一般都会用ObjectAnimator来改变某一对象的某一属性,但用ObjectAnimator有一定的限制,要想使用ObjectAnimator,应该满足以下条件:
· 对象应该有一个setter函数:set<PropertyName>(驼峰命名法)
· 如上面的例子中,像ofFloat之类的工场方法,第一个参数为对象名,第二个为属性名,后面的参数为可变参数,如果values…参数只设置了一个值的话,那么会假定为目的值,属性值的变化范围为当前值到目的值,为了获得当前值,该对象要有相应属性的getter方法:get<PropertyName>
· 如果有getter方法,其应返回值类型应与相应的setter方法的参数类型一致。
如果上述条件不满足,则不能用ObjectAnimator,应用ValueAnimator代替。
tv=(TextView)findViewById(R.id.textview1);
btn=(Button)findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
ObjectAnimatoroa=ObjectAnimator.ofFloat(tv, "alpha", 0f, 1f);
oa.setDuration(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.5TypeEvalutors
根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值,android提供了以下几个evalutor:
· IntEvaluator:属性的值类型为int;
· FloatEvaluator:属性的值类型为float;
· ArgbEvaluator:属性的值类型为十六进制颜色值;
· TypeEvaluator:一个接口,可以通过实现该接口自定义Evaluator。
自定义TypeEvalutor很简单,只需要实现一个方法,如FloatEvalutor的定义:
public classFloatEvaluator implements TypeEvaluator {
public Object evaluate(float fraction, Object startValue, ObjectendValue) {
float startFloat = ((Number)startValue).floatValue();
return startFloat + fraction * (((Number)endValue).floatValue() - startFloat);
}
}
根据动画执行的时间跟应用的Interplator,会计算出一个0~1之间的因子,即evalute函数中的fraction参数,通过上述FloatEvaluator应该很好看出其意思。
3.6TimeInterplator
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中的子元素可以通过setVisibility使其Visible、Invisible或Gone,当有子元素可见性改变时(VISIBLE、GONE),可以向其应用动画,通过LayoutTransition类应用此类动画:
transition.setAnimator(LayoutTransition.DISAPPEARING,customDisappearingAnim);
通过setAnimator应用动画,第一个参数表示应用的情境,可以以下4种类型:
· APPEARING 当一个元素在其父元素中变为Visible时对这个元素应用动画
· CHANGE_APPEARING 当一个元素在其父元素中变为Visible时,因系统要重新布局有一些元素需要移动,对这些要移动的元素应用动画
· DISAPPEARING 当一个元素在其父元素中变为GONE时对其应用动画
· CHANGE_DISAPPEARING 当一个元素在其父元素中变为GONE时,因系统要重新布局有一些元素需要移动,这些要移动的元素应用动画.
第二个参数为一Animator。
mTransitioner.setStagger(LayoutTransition.CHANGE_APPEARING,30);
此函数设置动画延迟时间,参数分别为类型与时间。
3.8Keyframes
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);
PropertyValuesHolderpvhRotation = PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2,kf4, kf3);
ObjectAnimator rotationAnim =ObjectAnimator.ofPropertyValuesHolder(btn2, pvhRotation);
rotationAnim.setDuration(2000);
上述代码的意思为:设置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对象。
用下面的代码可以实现同样的效果(上述代码时间值是线性,变化均匀):
ObjectAnimatoroa=ObjectAnimator.ofInt(btn2, "width", 400,200,400,100,500);
oa.setDuration(2000);
oa.start();
3.9Animating Views
在View Animation中,对View应用Animation并没有改变View的属性,动画的实现是通过其Parent View实现的,在View被drawn时Parents View改变它的绘制参数,draw后再改变参数invalidate,这样虽然View的大小或旋转角度等改变了,但View的实际属性没变,所以有效区域还是应用动画之前的区域,比如你把一按钮放大两倍,但还是放大这前的区域可以触发点击事件。为了改变这一点,在Android 3.0中给View增加了一些参数并对这些参数增加了相应的getter/setter函数(ObjectAnimator要用这些函数改变这些属性):
· translationX,translationY:View相对于原始位置的偏移量
· rotation,rotationX,rotationY:旋转,rotation用于2D旋转角度,3D中用到后两个
· scaleX,scaleY:缩放比
· x,y:View的最终坐标,是View的left,top位置加上translationX,translationY
· alpha:透明度
跟位置有关的参数有3个,以X坐标为例,可以通过getLeft(),getX(),getTranslateX()获得,若有一Button btn2,布局时其坐标为(40,0):
//应用动画之前
btn2.getLeft(); //40
btn2.getX(); //40
btn2.getTranslationX(); //0
//应用translationX动画
ObjectAnimatoroa=ObjectAnimator.ofFloat(btn2,"translationX", 200);
oa.setDuration(2000);
oa.start();
/*应用translationX动画后
btn2.getLeft(); //40
btn2.getX(); //240
btn2.getTranslationX(); //200
*/
//应用X动画,假设没有应用之前的translationX动画
ObjectAnimatoroa=ObjectAnimator.ofFloat(btn2, "x", 200);
oa.setDuration(2000);
oa.start();
/*应用X动画后
btn2.getLeft(); //40
btn2.getX(); //200
btn2.getTranslationX(); //160
*/
无论怎样应用动画,原来的布局时的位置通过getLeft()获得,保持不变;
X是View最终的位置;
translationX为最终位置与布局时初始位置这差。
所以若就用translationX即为在原来基础上移动多少,X为最终多少
getX()的值为getLeft()与getTranslationX()的和
对于X动画,源代码是这样的:
case X:
info.mTranslationX = value -mView.mLeft;
break;
Property Animation也可以在XML中定义
· <set>- AnimatorSet
· <animator>- ValueAnimator
· <objectAnimator>- ObjectAnimator
XML文件应放大/res/animator/中,通过以下方式应用动画:
AnimatorSet set = (AnimatorSet)AnimatorInflater.loadAnimator(myContext, R.anim.property_animator);
set.setTarget(myObject);
set.start();
3.10ViewPropertyAnimator
如果需要对一个View的多个属性进行动画可以用ViewPropertyAnimator类,该类对多属性动画进行了优化,会合并一些invalidate()来减少刷新视图,该类在3.1中引入。
以下两段代码实现同样的效果:
PropertyValuesHolder pvhX =PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();
myView.animate().x(50f).y(100f);
android 动画的使用
Android Animations动画使用详解
一、动画类型
Android的animation由四种类型组成:alpha、scale、translate、rotate
XML配置文件中
alpha | 渐变透明度动画效果 |
scale | 渐变尺寸伸缩动画效果 |
translate | 画面转换位置移动动画效果 |
rotate | 画面转移旋转动画效果 |
Java Code代码中
AlphaAnimation | 渐变透明度动画效果 |
ScaleAnimation | 渐变尺寸伸缩动画效果 |
TranslateAnimation | 画面转换位置移动动画效果 |
RotateAnimation | 画面转移旋转动画效果 |
二、Android动画模式
Animation主要有两种动画模式:tweened 和 frame
- 一种是tweened animation(渐变动画)
XML中 | JavaCode |
alpha | AlphaAnimation |
scale | ScaleAnimation |
- 一种是frame by frame(画面转换动画)
XML中 | JavaCode |
translate | TranslateAnimation |
rotate | RotateAnimation |
三、XML文件中定义动画
① 打开Eclipse,新建Android工程
② 在res目录中新建anim文件夹
③ 在anim目录中新建一个myanim.xml(注意文件名小写)
④ 加入XML的动画代码
1. <?xmlversion="1.0" encoding="utf-8"?>
2. <setxmlns:android="http://schemas.android.com/apk/res/android">
3. <alpha/>
4. <scale/>
5. <translate/>
6. <rotate/>
7. </set>
四、Android XML动画解析
1. Alpha
1. <?xmlversion="1.0" encoding="utf-8"?>
2. <setxmlns:android="http://schemas.android.com/apk/res/android" >
3. <alpha
4. android:fromAlpha="0.1"
5. android:toAlpha="1.0"
6. android:duration="3000"
7. />
8. <!-- 透明度控制动画效果 alpha
9. 浮点型值:
10. fromAlpha 属性为动画起始时透明度
11. toAlpha 属性为动画结束时透明度
12. 说明:
13. 0.0表示完全透明
14. 1.0表示完全不透明
15. 以上值取0.0-1.0之间的float数据类型的数字
16.
17. 长整型值:
18. duration 属性为动画持续时间
19. 说明:
20. 时间以毫秒为单位
21. -->
22. </set>
2.Scale
1. <?xmlversion="1.0" encoding="utf-8"?>
2. <setxmlns:android="http://schemas.android.com/apk/res/android">
3. <scale
4. android:interpolator=
5. "@android:anim/accelerate_decelerate_interpolator"
6. android:fromXScale="0.0"
7. android:toXScale="1.4"
8. android:fromYScale="0.0"
9. android:toYScale="1.4"
10. android:pivotX="50%"
11. android:pivotY="50%"
12. android:fillAfter="false"
13. android:duration="700"/>
14. </set>
15. <!-- 尺寸伸缩动画效果 scale
16. 属性:interpolator 指定一个动画的插入器
17. 在我试验过程中,使用android.res.anim中的资源时候发现
18. 有三种动画插入器:
19. accelerate_decelerate_interpolator 加速-减速动画插入器
20. accelerate_interpolator 加速-动画插入器
21. decelerate_interpolator 减速- 动画插入器
22. 其他的属于特定的动画效果
23. 浮点型值:
24.
25. fromXScale 属性为动画起始时 X坐标上的伸缩尺寸
26. toXScale 属性为动画结束时 X坐标上的伸缩尺寸
27.
28. fromYScale 属性为动画起始时Y坐标上的伸缩尺寸
29. toYScale 属性为动画结束时Y坐标上的伸缩尺寸
30.
31. 说明:
32. 以上四种属性值
33.
34. 0.0表示收缩到没有
35. 1.0表示正常无伸缩
36. 值小于1.0表示收缩
37. 值大于1.0表示放大
38.
39. pivotX 属性为动画相对于物件的X坐标的开始位置
40. pivotY 属性为动画相对于物件的Y坐标的开始位置
41.
42. 说明:
43. 以上两个属性值从0%-100%中取值
44. 50%为物件的X或Y方向坐标上的中点位置
45.
46. 长整型值:
47. duration 属性为动画持续时间
48. 说明: 时间以毫秒为单位
49.
50. 布尔型值:
51. fillAfter属性当设置为true ,该动画转化在动画结束后被应用
52. -->
3.Translate
1. <?xmlversion="1.0" encoding="utf-8"?>
2. <setxmlns:android="http://schemas.android.com/apk/res/android">
3. <translate
4. android:fromXDelta="30"
5. android:toXDelta="-80"
6. android:fromYDelta="30"
7. android:toYDelta="300"
8. android:duration="2000"
9. />
10. <!-- translate 位置转移动画效果
11. 整型值:
12. fromXDelta 属性为动画起始时 X坐标上的位置
13. toXDelta 属性为动画结束时 X坐标上的位置
14. fromYDelta 属性为动画起始时 Y坐标上的位置
15. toYDelta 属性为动画结束时 Y坐标上的位置
16. 注意:
17. 没有指定fromXTypetoXType fromYType toYType 时候,
18. 默认是以自己为相对参照物
19. 长整型值:
20. duration 属性为动画持续时间
21. 说明: 时间以毫秒为单位
22. -->
23. </set>
4.Rotate
1. <?xmlversion="1.0" encoding="utf-8"?>
2. <setxmlns:android="http://schemas.android.com/apk/res/android">
3. <rotate
4. android:interpolator="@android:anim/accelerate_decelerate_interpolator"
5. android:fromDegrees="0"
6. android:toDegrees="+350"
7. android:pivotX="50%"
8. android:pivotY="50%"
9. android:duration="3000"/>
10. <!-- rotate 旋转动画效果
11. 属性:interpolator 指定一个动画的插入器
12. 在我试验过程中,使用android.res.anim中的资源时候发现
13. 有三种动画插入器:
14. accelerate_decelerate_interpolator 加速-减速动画插入器
15. accelerate_interpolator 加速-动画插入器
16. decelerate_interpolator 减速- 动画插入器
17. 其他的属于特定的动画效果
18.
19. 浮点数型值:
20. fromDegrees 属性为动画起始时物件的角度
21. toDegrees 属性为动画结束时物件旋转的角度可以大于360度
22.
23.
24. 说明:
25. 当角度为负数——表示逆时针旋转
26. 当角度为正数——表示顺时针旋转
27. (负数from——to正数:顺时针旋转)
28. (负数from——to负数:逆时针旋转)
29. (正数from——to正数:顺时针旋转)
30. (正数from——to负数:逆时针旋转)
31.
32. pivotX 属性为动画相对于物件的X坐标的开始位置
33. pivotY 属性为动画相对于物件的Y坐标的开始位置
34.
35. 说明: 以上两个属性值从0%-100%中取值
36. 50%为物件的X或Y方向坐标上的中点位置
37.
38. 长整型值:
39. duration 属性为动画持续时间
40. 说明: 时间以毫秒为单位
41. -->
42. </set>
XML中使用动画效果
1. public staticAnimation loadAnimation (Context context, int id)
2. //第一个参数Context为程序的上下文
3. //第二个参数id为动画XML文件的引用
4. //例子:
5. myAnimation= AnimationUtils.loadAnimation(this, R.anim.my_action);
6. //使用AnimationUtils类的静态方法loadAnimation()来加载XML中的动画XML文件
五、Java代码中定义动画
1. //在代码中定义动画实例对象
2. privateAnimation myAnimation_Alpha;
3. privateAnimation myAnimation_Scale;
4. privateAnimation myAnimation_Translate;
5. privateAnimation myAnimation_Rotate;
6.
7. //根据各自的构造方法来初始化一个实例对象
8. myAnimation_Alpha= new AlphaAnimation(0.1f, 1.0f);
9.
10. myAnimation_Scale = new ScaleAnimation(0.0f, 1.4f, 0.0f,1.4f,
11. Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
12.
13. myAnimation_Translate = new TranslateAnimation(30.0f,-80.0f, 30.0f, 300.0f);
14.
15. myAnimation_Rotate = new RotateAnimation(0.0f, +350.0f,
16. Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
六、Android 代码动画解析
1.AlphaAnimation
AlphaAnimation类对象定义
1. 1.private AlphaAnimation myAnimation_Alpha;
AlphaAnimation类对象构造
1. AlphaAnimation(floatfromAlpha, float toAlpha)
2. //第一个参数fromAlpha为动画开始时候透明度
3. //第二个参数toAlpha为动画结束时候透明度
4. myAnimation_Alpha =new AlphaAnimation(0.1f, 1.0f);
5. //说明:
6. // 0.0表示完全透明
7. // 1.0表示完全不透明
设置动画持续时间
1. myAnimation_Alpha.setDuration(5000);
2. //设置时间持续时间为 5000毫秒
2. ScaleAnimation
ScaleAnimation类对象定义
1. privateScaleAnimation myAnimation_Scale;
ScaleAnimation类对象构造
1. ScaleAnimation(floatfromX, float toX, float fromY, float toY,
2. int pivotXType, float pivotXValue,int pivotYType, float pivotYValue)
3. //第一个参数fromX为动画起始时 X坐标上的伸缩尺寸
4. //第二个参数toX为动画结束时 X坐标上的伸缩尺寸
5. //第三个参数fromY为动画起始时Y坐标上的伸缩尺寸
6. //第四个参数toY为动画结束时Y坐标上的伸缩尺寸
7. /*说明:
8. 以上四种属性值
9. 0.0表示收缩到没有
10. 1.0表示正常无伸缩
11. 值小于1.0表示收缩
12. 值大于1.0表示放大
13. */
14. //第五个参数pivotXType为动画在X轴相对于物件位置类型
15. //第六个参数pivotXValue为动画相对于物件的X坐标的开始位置
16. //第七个参数pivotXType为动画在Y轴相对于物件位置类型
17. //第八个参数pivotYValue为动画相对于物件的Y坐标的开始位置
18. myAnimation_Scale = new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f,
19. Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
设置动画持续时间
1. myAnimation_Scale.setDuration(700);
2. //设置时间持续时间为 700毫秒
3.TranslateAnimation
ranslateAnimation类对象定义
1. privateTranslateAnimation myAnimation_Translate;
TranslateAnimation类对象构造
1. TranslateAnimation(floatfromXDelta, float toXDelta,
2. float fromYDelta, float toYDelta)
3. //第一个参数fromXDelta为动画起始时 X坐标上的移动位置
4. //第二个参数toXDelta为动画结束时 X坐标上的移动位置
5. //第三个参数fromYDelta为动画起始时Y坐标上的移动位置
6. //第四个参数toYDelta为动画结束时Y坐标上的移动位置
设置动画持续时间
1. myAnimation_Translate= new TranslateAnimation(10f, 100f, 10f, 100f);
2. myAnimation_Translate.setDuration(2000);
3. //设置时间持续时间为 2000毫秒
4. RotateAnimation
RotateAnimation类对象定义
1. privateRotateAnimation myAnimation_Rotate;
RotateAnimation类对象构造
1. RotateAnimation(floatfromDegrees, float toDegrees,
2. int pivotXType, float pivotXValue,int pivotYType, float pivotYValue)
3. //第一个参数fromDegrees为动画起始时的旋转角度
4. //第二个参数toDegrees为动画旋转到的角度
5. //第三个参数pivotXType为动画在X轴相对于物件位置类型
6. //第四个参数pivotXValue为动画相对于物件的X坐标的开始位置
7. //第五个参数pivotXType为动画在Y轴相对于物件位置类型
8. //第六个参数pivotYValue为动画相对于物件的Y坐标的开始位置
9. myAnimation_Rotate =new RotateAnimation(0.0f, +350.0f,
10. Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
设置动画持续时间
1. myAnimation_Rotate.setDuration(3000);
2. //设置时间持续时间为 3000毫秒
如何Java代码中使用动画效果
使用从View父类继承过来的方法startAnimation()来为View或是子类View等等添加一个动画效果
1. public void startAnimation(Animation animation)
2. view.startAnimation(myAnimation_Alpha);
3. view.startAnimation(myAnimation_Scale);
4. view.startAnimation(myAnimation_Translate);
5. view.startAnimation(myAnimation_Rotate);
Android动画---Animation Overview
Android框架提供了三种动画系统:属性动画(在Android3.0中被引入)和视图动画、绘图动画。前两种动画系统都是可行的选择,但是通常属性动画是首选的方法,因为它更加灵活,并提供了更多的功能。除了这两种动画系统之外,还能够利用绘图动画,它允许加载绘图资源并一帧一帧的来显示它们。
属性动画
在Android3.0中被引入(APILevel 11),属性动画系统会让任何对象具有动画属性,包括那些没有呈现在屏幕上的对象。这个系统是可扩展的,并且支持自定义的类型的动画属性。
视图动画
视图动画是一个比较旧的动画系统,并且它仅能用于View对象。这个动画系统相对与容易创建,并且对于应用程序中所遇到的大多数需求提供了足够的能力。
绘图动画涉及到绘图资源的像放电影一样的顺序显示,如果想要使用绘图资源来更容易的展现动画,如何位图进度条等,那么这种动画方法是有用的。
Android属性动画---PropertyAnimation(一)
本文译自:http://developer.android.com/guide/topics/graphics/prop-animation.html
属性动画系统是一个健壮的框架,它几乎可以允许把任何对象变成动画。可以根据时间的推移来改变任何对象的属性来定义一个动画,而不用关心该对象是否要绘制在屏幕上。属性动画是在指定的时间长度上改变一个属性(对象中的一个成员字段)的值。要让某些对象变成动画,就要给该对象指定想要的动画属性,如果对象在屏幕上的位置、动画的停留时间以及动画之间的值等。
属性动画系统可以定义以下动画特性:
1. 持续时间(Duration):指定动画的持续时间。默认长度是300毫秒。
2. 时间插值(Timeinterpolation):这个值能够做为计算当前动画运行时间的函数的属性值来指定,它决定动画的变化频率。
3. 重复次数和行为(Repeatcount and behavior)
这个属性能够指定在动画结束时是否重新播放动画,以及重复播放的次数。还能够指定动画是否能够反向回播,如果设置了反向回播,那么动画就会先向前再向后,重复播放,直到达到播放次数。
4. 动画集合(Animatorsets):你能够把动画组织到一个逻辑集合中,然后或者同时、或者顺序的、或者延迟播放它们。
5. 帧刷新延迟(Framerefresh delay):你能够指定动画帧的刷新频率。默认是每10秒中刷新一次,但是应用程序最终的刷新帧的速度依赖与系统的繁忙程度以及系统能够提供的底层定时器的反应速度。
属性动画是如何工作的
首先,让我们用一个简单的例子来看一下动画的工作方式。图1绘制了一个假想的动画对象,它用x属性来表示其在屏幕上的水平位置。动画的持续时间被设置为40毫秒,并且移动的距离是40个像素。每10毫秒,是默认的帧刷新频率,即每10毫秒对象水平移动10个像素。在40毫秒结束时,动画停止,并且动画要停留在水平40像素点的位置上。这是一个线性插值的动画示例,意味着动画匀速运动。
图1.线性动画示例
还可以指定非线性差值的动画。图2假设了一个加速开始、减速结束的动画对象,该对象依然在40毫秒内移动了40个像素,但是非线性的。在开始的时候,这个动画加速运动到一半的位置,然后开始减速运动直到动画结束。如图2所示,对象运行的距离在开始和结束阶段要比中间部分短。
图2.非线性动画的示例
接下来让我们更详细的了解属性动画系统的重要组件是如何计算上图所示动画。图3绘制了主类和其他类是如何一起工作的。
图3.动画的计算方式
ValueAnimator对象保持着动画的时间轨迹,如动画的运行时间,以及动画属性的当前值。
ValueAnimator类封装了一个TimeInterpolator类,这个类定义了动画的差值,和一个TypeEvaluator类,这个类定义动画属性值的计算方式。例如,在图2中TimeInterpolator对象使用AccelerateDecelerateInterpolator定义,TypeEvaluator使用了IntEvaluator定义。
要启动一个动画,就要创建一个ValueAnimator对象,并且要给该对象设置想要的动画的属性的开始和结束值,以及动画的持续时间。在调用start()方法开始动画的时候,整个动画期间,ValueAnimator对象会根据动画的持续时间和已经执行的时间,在0和1之间,计算一个elapsed fraction(过去系数)。这个系数代表了动画已经完成的百分比,0意味着0%、1意味着100%。例如,图1中,在t = 10毫秒处的过去系数是0.25,因为总的持续时间是t = 40毫秒。
当ValueAnimator对象完成过去系数的计算时,它会调用当前设置的TimeInterpolator对象,来计算一个差值系数(interpolated fraction)。差值系数(interpolated fraction)把过去系数(elapsedfraction)映射到一个新的考虑设置时间差值的系数。例如,在图2中,因为动画是慢慢的加速,因此在t=10毫秒时,差值系数大约是0.15,它比过去系数(elapsed fraction)0.25要小。在图1中,差值系数(interpolated fraction)与过去系数(elapsed fraction)始终相同。
在计算差值系数(interpolated fraction)时,ValueAnimator对象会调用相应的TypeEvaluator对象,基于差值系数、动画的开始值、结束值,来计算动画的属性值。例如,在图2中,在t = 10毫秒处,差值系数是0.15,因此在此时的属性值应该是0.15*(40 – 0)= 6。
在API Demos示例工程中的com.example.android.apis.animation包,提供了很多如何使用属性动画系统的例子。(http://developer.android.com/tools/samples/index.html)
Android属性动画---Property Animation(二)
本文译自:http://developer.android.com/guide/topics/graphics/prop-animation.html
属性动画与视图动画的差异
视图动画提供了只让View对象具有动画效果的能力,因此想要非View对象具有动画效果,就得自己实现动画效果的代码。事实上,视图动画系统也受到了限制,它只会把很少的View对象的特征暴露给动画效果,如例如,View对象的缩放和旋转,但是没有背景色,等等。
视图动画的另一个缺点是,它仅能够在绘制View对象时被修改,并且不是实际的View对象本身。例如,如果要让一个按钮,以动画的形式穿越屏幕,按钮正确的绘制了,但是点击按钮的实际位置却不会改变,因此必须自己来实现这种处理逻辑。
在属性动画系统中,这些现在被彻底删除,并且能够让任何对象的任何属性具有动画效果(View对象和非View对象),并且能够实际修改对象自身。属性动画在动画执行方面也更加健壮。在高层次上,可以给想要动画效果的属性分配动画执行器,如颜色、位置、尺寸以及能够定义的动画特性(如插值和多个动画的同步等)。
但是,视图动画系统需要较少的创建时间和编写较少的代码。如果视图动画能够满足需求,或者既存的代码已经做了想要完成的动画效果,就不需要使用属性动画效果了。针对不同的情况来选择使用这两种不同的动画系统。
Android属性动画---PropertyAnimation(三)
本文译自:http://developer.android.com/guide/topics/graphics/prop-animation.html
API概要
在android.animation包中能够找大多数属性动画系统的API。因为视图动画系统已经在android.view.animation包中定义了很多插值,因此在属性动画系统中也能够使用这些插值。下列表格中介绍了属性动画系统的主要组件。
Animator类提供了创建动画的基本架构。通常不会直接使用这个类,因为它只提供了基本功能,因此要完全的支持动画值就必须扩展这个类,下表列出了Animator的子类。
表1.Animators
类 | 说明 |
ValueAnimator | 用于计算处理动画属性值的主要属性动画时序引擎。它有所有的计算动画值的核心功能,并包含了每个动画的时序细节、动画是否重复的信息、监听接收更新事件和设置评估定制类型的能力。有两类动画属性:1.计算动画处理的值;2.把这些值设置到要进行动画处理的对象和属性上。ValueAnimator类不执行第二类属性,因此必须通过ValueAnimator对象来监听被计算值的变化,并且要自己修改想要的动画对象的逻辑。更多的信息请看用ValueAnimator类来进行动画处理。(http://developer.android.com/guide/topics/graphics/prop-animation.html#value-animator) |
ObjectAnimator | ValueAnimator类的一个子类,它允许给目标对象和对象属性设置动画。这个类在计算新的动画值的时候,会更新属性的坐标。大多数时候都会使用ObjectAnimator类,因为它使得动画值的处理更加容易。但是,有些时候也会直接使用ValueAnimator类,因为ObjectAnimator类有更多的限制,如在目标对象上需要指定用于呈现的acessor方法。 |
AnimatorSet | 提供了一种把动画组织到一起的机制,以便它们能够彼此相互关联的运行。你能够设置动画在一起播放、顺序的播放、或者在指定的延时之后播放。更多的信息请看“用Animator Sets来编排多个动画” |
评价器会告诉属性动画系统如何计算给定属性的值。它们利用Animator类提供时序数据:动画的开始和结束值,以及基于这些数据计算得来的属性动画值。属性动画系统提供了下列评价器:
表2.Evaluators
Class/Interface | 说明 |
IntEvaluator | 默认的用于评价int类型属性计算值的评价器 |
FlaoatEvaluator | 默认的用于评价float类型属性计算值的评价器 |
ArgbEvaluator | 默认的用于评价颜色属性计算值的评价器,颜色属性值用十六进制表示。 |
TypeEvaluator | 允许创建自定义评价器的接口。如果要让一个非int、float、颜色类型的属性具有动画效果,就必须实现这个TypeEvaluator接口,用它来指定如何计算对象属性动画值。如果想要处理有别于int、float和颜色类型默认行为的动画,也能够给它们指定一个自定义的TypeEvaluator。如何编写自定义的评价器,请看“使用TypeEvaluator” |
时间差值给动画中的时间函数定义了一个用于计算的具体的值。例如,一个线性过渡的动画,意味着整个动画期间动画都会均匀的移动,或者例如加速开始,减少结束的非线性动画。表3介绍了被包含在android.view.animation包中差值。如果那里没有适合你需要的差值,你可以实现TimeInterpolator接口,创建自己的差值。如何编写自定义差值的更多信息,请看“使用差值”。
表3.Interpolators
Class/Interface | 说明 |
AccelerateDecelerateInterpolator | 变化频率在开始和结尾处慢,而在中间部分加速 |
AccelerateInterpolator | 变化频率在开始慢,然后加速 |
AnticipateInterpolator | 先向后,然后向前抛出(抛物运动) |
AnticipateOvershootInterpolator | 先向后,向前抛出并超过目标值,然后最终返回到目标值。 |
BounceInterpolator | 在结束时反弹 |
CycleInterpolator | 用指定的循环数,重复播放动画 |
DecelerateInterpolator | 变化频率是快出,然后减速 |
LinearInterpolator | 固定的变化频率 |
OvershootInterpolator | 向前抛出,并超过目标值,然后再返回 |
TimeInterpolator | 实现自定义插值的一个接口 |
Android属性动画---Property Animation(四)
用ValueAnimator来制作动画
ValueAnimator类通过设定动画过程中的int、float或颜色值,来指定动画播放期间的某些类型的动画值。通过ValueAnimator类的一个工厂方法来获取一个ValueAnimator对象:ofInt()、ofFloat()、ofObject()。例如:
ValueAnimatoranimation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.start();
在这段代码中,当start()方法开始执行时,ValueAnimator对象会在1000毫秒的动画期间内,在0和1之间开始计算动画的值。
还可以通过下面的做法来指定自定义的动画类型:
ValueAnimatoranimation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue,endPropertyValue);
animation.setDuration(1000);
animation.start();
在这段代码中,在start()方法开始执行的时候,ValueAnimator对象会在1000毫秒的动画期间内,使用由MyTypeEvaluator对象提供的逻辑,在startPropertyValue和endPropertyValue之间,开始计算动画的值。
但是,在前一个代码片段中,不会对一个对象形成实际的影响,因为ValueAnimator对象没有直接在对象或属性上执行操作。这么做的最大可能是用这些计算值来修改那些想要动画效果的对象。通过定义ValueAnimator类中响应的事件监听器,来处理动画执行期间的重要事件,如帧更新等。当监听器执行的时候,就能够通过调用getAnimateValue()方法获得指定帧的刷新的计算值。有关监听器的更多信息,请看“动画监听器”。
用ObjectAnimator来制作动画
ObjectAnimator类是ValueAnimator类的一个子类,并且把时序引擎和ValueAnimator对象的计算值组合到一起,让目标对象的命名属性具备动画能力。这样使得让任意对象具有动画效果变的更加容易,如不在需要实现ValueAnimator.AnimatorUpdateListener接口,因为被动画的属性会自动的更新。
实例化一个ObjectAnimator对象与实例化一个ValueAnimator对象类似,但是,它还需要跟动画期间的参数一起,指定动画对象和对象动画属性(用一个字符串)的名字:
ObjectAnimatoranim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
anim.setDuration(1000);
anim.start();
要正确的更新ObjectAnimator对象的属性,必须做以下事情:
1. 动画效果的属性必须有一个set<propertyName>格式的设置器方法。因为在动画处理期间,ObjectAnimator对象会自动的更新对应的动画效果属性,所以它必须使用这个设置器方法来访问对应的属性。例如,如果属性名是foo,那么就需要有一个setFoo()方法,如果这个设置器方法不存在,你有三种选择:
A. 如果你权利这么做,就要在这个类中添加设置器方法;
B. 使用一个你有权改变的包装器类,并且这个包装器能够用一个有效的设置方法来接收动画值,而且还要能够把这个值转发给初始对象。
C. 使用ValueAnimator类来代替。
2. 如果你只在ObjectAnimator类的一个工厂方法中指定了一个values…参数,那么该值会被假定为动画的结束值。因此,该对象的动画效果属性就必须要有一个获取方法,用于获得动画的开始值。这个获取方法必须使用get<propertyName>()格式。例如,属性是foo,就必须有一个getFoo方法。
3. 动画属性的获取(如果需要)和设置方法必须操作相同类型的指定给ObjectAnimator对象开始和结束值。例如,如果构建一个下面这样的ObjectAnimator对象,就必须要有targetObejct.setPropName(float)和targetObject.getPropName(float)方法:
ObjectAnimator.ofFloat(targetObject,"propName",1f)
4. 根据属性或对象上的动画效果,可能需要调用View对象上的invalidate()方法,在更新动画效果时,强制屏幕重绘自己。在onAnimationUpdate()回调方法中做这件事情。例如,一个绘图对象的颜色属性的动画效果,在队形重绘自己时,才会将变化结果更新到屏幕上。在View对象上的所有的属性的设置器,如setAlpha()和setTranslationX()会正确的让View对象失效,因此在调用这些方法设置新的值时候,你不需做失效这件事。有关监听器的更多信息,请看“动画监听器”。
Android属性动画---PropertyAnimation(五)
用AnimatorSet类来编排多个动画
在很多场景中,一个动画的播放要依赖与另一个动画的开始或结束。Android系统让你把这些相互依赖的动画绑定到一个AnimatorSet对象中,以便能够指定它们是同时的、顺序的、或在指定的延时之后来播放。AnimatorSet对象也能够彼此嵌套。
以下示例代码来自Bouncing Balls示例,它按照以下方式播放Animator对象:
1. 播放bounceAnim
2. 同时播放squashAnim1、squashAnim2、stretchAnim1和stetchAnim2
3. 播放bounceBackAnim
4. 播放fadeAnim
AnimatorSetbouncer = new AnimatorSet();
bouncer.play(bounceAnim).before(squashAnim1);
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
bouncer.play(bounceBackAnim).after(stretchAnim2);
ValueAnimatorfadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
AnimatorSetanimatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
animatorSet.start();
关于如何使用动画集的完整示例,请看APIDemo中的BouncingBalls示例。
动画监听器
使用下列介绍的监听器能够监听动画播放期间的重要事件:
1. Animator.AnimatorListener
onAnimationStart()---动画开始的时候被调用
onAnimationEnd()---动画结束的时候被调用,它不管动画是如何结束的。
onAnimationRepeate()---动画重复播放的时候被调用
onAnimationCancel()---动画被取消播放的时候被调用。
2. ValueAnimator.AnimatorUpdateListener
onAnimationUpdate()---在动画的帧上调用这个方法。通过监听这个事件,使用在动画期间由ValueAnimator对象产生的计算值。要使用这个值,就要用getAnimateValue()方法查询传递到事件中的ValueAnimator对象,以便获得当前的动画值。如果使用ValueAnimator类,那么实现这个监听器是必须的。
根据属性或对象的动画效果,可能需要调用View对象上的invalidate()方法,用新的动画值来强制屏幕的指定区域进行重绘。例如,Drawable对象的颜色属性的动画效果,在对象重绘自己的时候,只会导致屏幕的更新。在View对象上的所有属性的设置器,如setAlpha()、setTranslationX()等方法都会正确的让View对象失效,因此在调用这些方法设置新值的时候,你不需要让该View对象失效。
如果不实现Animator.AnimatorListener接口的所有方法,你能够继承AnimatorListenerAdapter类,来代替对Animator.AnimatorListener接口的实现。AnimatorListenerAdapter类对这些方法提供了空的实现,你可以选择性的重写这些方法。
例如,APIDemo中的Bouncing Balls示例就只创建了一个AnimatorListenerdapter类的onAnimationEnd()回调方法:
ValueAnimatorAnimator fadeAnim =ObjectAnimator.ofFloat(newBall,"alpha",1f,0f);
fadeAnim.setDuration(250);
fadeAnim.addListener(newAnimatorListenerAdapter(){
publicvoid onAnimationEnd(Animator animation){
balls.remove(((ObjectAnimator)animation).getTarget());
}
Android属性动画---PropertyAnimation(六)
对于ViewGroups对象布局变化的动画
属性动画系统给ViewGroup对象的动画变化提供了与View对象一样容易动画处理方法。
使用LayoutTransition类在ViewGroup内部处理布局变化的动画。当调用一个View对象的setVisibility()方法,或者设置该View的GONE常量,或者把该View对象添加到ViewGroup中(或者从ViewGroup中删除)时,在ViewGroup内部的View对象就能够实现时隐时现的动画效果。当在ViewGroup对象中添加或删除View对象时,其中的其他View对象也能够动画移动到新的位置。在LayoutTransition对象内通过调用setAnimator()方法,并且在传递给该方法的Animator对象参数中带有下列LayoutTransition常量之一,就能够定义该常量所代表的动画:
1. APPEARING---一个标记,它指示要在容器中正在显示的项目上运行动画;
2. CHANGEAPPEARING---一个标记,它指示在容器中由于新项目的出现而导致其他项目变化所要运行的动画;
3. DISAPPEARING---一个标记,它指示一个从容器中消失的项目所要运行的动画;
4. CHANGE_DISAPPEARING---一个标记,它指示由于一个项目要从容器中消失而导致其他项目的变化,所要运行的动画。
能够给这四种事件类型定义自定义动画,以便定制自己的布局过渡效果,也可以告诉动画系统只使用默认的动画效果。
在APIDemo中的LayoutAnimations示例,显示了如何给布局的过渡定义动画效果,并且在想要动画效果的View对象上设置动画。
LayoutAnimationsByDefault类以及它对应的layout_animations_by_default.xml布局资源文件显示了如何在XML中启用ViewGroup对象的默认布局过渡效果。需要做的事情仅仅是把ViewGroup元素的android.animateLayoutchanges属性设置为true。例如:
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="@+id/verticalContainer"
android:animateLayoutChanges="true"/>
如果把这个属性设置为true,那么在该ViewGroup对象中添加或删除View对象,以及ViewGroup对象中其他的View对象都会自动的具有动画效果。
使用TypeEvaluator
如果想要的动画类型是Android系统所未知的,那么通过实现TypeEvaluator接口就能够创建自己的评价器。Android系统已知的类型是int、float或颜色(color),分别有IntEvaluator、FloatEvaluator和ArgbEvaluator类型的评价器所支持。
在TypeEvaluator接口中只有一个要实现的方法:evaluate()方法。这个方法允许正在使用的动画处理器返回一个适用于于当前动画时点动画属性值,FloatEvaluator类演示了这个方法是如何做这件事的:
publicclass FloatEvaluator implements TypeEvaluator {
public Object evaluate(float fraction, Object startValue, ObjectendValue) {
float startFloat = ((Number) startValue).floatValue();
return startFloat + fraction * (((Number) endValue).floatValue()- startFloat);
}
}
注意:当ValueAnimator对象(或ObjectAnimator对象)运行时,它会计算当前的动画播放比例(一个0到1之间的值),然后根据你所使用的插值类型来计算一个要插入的动画的版本。插值比例是由TypeEvaluator对象通过fraction参数接收来的,因此在计算动画值的时候,不需要考虑插值。
Android属性动画---PropertyAnimation(七)
使用插补器
插补器定义了怎样在动画内指定用于时间函数的计算值。例如,指定贯穿整个动画期间的线性播放动画,意味在动画整个时间里都是均匀的移动,也能够指定非线性动画,如:在动画的开始或结尾部分使用加速或减速的动画。
在动画系统中的插补器会接收一个来自Animator对象的一个比例,它代表了动画已经过去的时间。插补器修改这个比例,使它与提供的目标动画类型相吻合。Android系统在android.view.animation包中提供了一组共通的插补器。如果这个包中没有适合你需要的,你可以实现TimeInterpolator接口来创建自己的插补器。
例如,以下是对AccelerateDecelerateInterpolator和LinearInterpolator插补器如何计算插补比例的比较。LinearInterpolator对延时比例没有影响,AccelerateDecelerateInterpolator会让动画加速进入,并减速退出。以下是这些插补器方法中定义的逻辑:
AccelerateDecelerateInterpolator
publicfloat getInterpolation(float input) {
return(float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
LinearInterpolator
publicfloat getInterpolation(float input) {
returninput;
}
下表列出了一个持续1000毫秒的动画通过插补器所计算的近似值:
播放时间(毫秒) | 播放比例/插值比例(线性) | 插值比例(加速/减速) |
0 | 0 | 0 |
200 | 0.2 | 0.1 |
400 | 0.4 | 0.345 |
600 | 0.6 | 0.8 |
800 | 0.8 | 0.9 |
1000 | 1 | 1 |
如上表所示,LinearInterpolator插补器的计算结果是匀速变化的,每200毫秒增加0.2。AccelerateDecelerateInterpolator插补器的计算结果在200毫秒到600毫秒之间比LinearInterpolator的计算结果要快,而在600毫秒到1000毫秒之间则比LinearInterpolator的计算结果要慢。
关键帧
有时间和值构成的Keyframe对象会定义动画在特定的时间点上特定的状态。每个关键帧还有它自己的插补器来控制当前关键帧与前一个关键帧之间的动画行为。
要实例化一个Keyframe对象,必须使用以下工厂方法之一:ofInt()、ofFloat()、或ofObject()。使用这些工厂方法来获取对应类型的关键帧,然后调用ofKeyframe工厂方法来获取一个PropertyValuesHolder对象,一旦获得了这个对象,就能够得到一个在PropertyValuesHolder对象中传递的动画制作器对象。以下代码演示了如何做这件事情:
Keyframekf0 = Keyframe.ofFloat(0f, 0f);
Keyframekf1 = Keyframe.ofFloat(.5f, 360f);
Keyframekf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolderpvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1,kf2);
ObjectAnimatorrotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation)
rotationAnim.setDuration(5000ms);
关于如何使用关键帧的完整的示例,情况APIDemo中的MultiPropertyAnimation示例。
http://developer.android.com/tools/samples/index.html
制作View动画
属性动画系统允许对View对象的动画进行简化处理,并且在视图动画系统上提供了一些优点。视图动画系统通过改变View对象的绘制方式来转换View对象。这种变换是在在每个View对象的容器中来处理的,因为View对象本身没有执行这种处理的属性。这种处理会导致View对象产生动画效果,但却不会改变View对象自身。这样即使在屏幕的不同的位置上绘制了View对象,该对象依然会保留在它的原始位置上。在Android3.0中,添加了新的属性和对象的getter和setter方法,来消除这一缺陷。
属性动画系统能够通过改变View对象中的实际属性,让View对象在屏幕上展现动画效果。另外,View对象也会自动的调用invalidate()方法,在属性发生变化时来属性屏幕。在View类中便于动画设置的新属性有:
1. translationX和translationY:这两个属性作为一种增量来控制着View对象从它布局容器的左上角坐标开始的位置。
2. rotation、rotationX和rotationY:这三个属性控制View对象围绕支点进行2D和3D旋转。
3. scaleX和scaleY:这两个属性控制着View对象围绕它的支点进行2D缩放。
4. pivotX和pivotY:这两个属性控制着View对象的支点位置,围绕这个支点进行旋转和缩放变换处理。默认情况下,该支点的位置就是View对象的中心点。
5. x和y:这是两个简单实用的属性,它描述了View对象在它的容器中的最终位置,它是最初的左上角坐标和translationX和translationY值的累计和。
6. alpha:它表示View对象的alpha透明度。默认值是1(不透明),0代表完全透明(不可见)。
要让一个View对象的属性具有动画效果,如它的颜色或旋转值等,就需要创建一个属性动画制作器,并给对象属性指定想要的动画效果,如:
ObjectAnimator.ofFloat(myView,"rotation",0f,360f);
Android属性动画---PropertyAnimation(八)
用ViewPropertyAnimator制作动画
ViewPropertyAnimator类使用一个单一的Animator对象,给一个View对象的几个动画属性平行处理提供一种简单的方法。它的行为非常像ObjectAnimator类,因为它修改了View对象属性的实际的值,但是当多个动画属性同时处理时,它会更加高效。另外,使用ViewPropertyAnimator类的代码更加简洁和易于阅读。以下代码片段显示了在同时处理View对象的x和y属性动画效果时,使用多个ObjectAnimator对象、一个单独的ObjectAnimator对象和ViewPropertyAnimator对象之间的差异:
过个ObjectAnimator对象:
ObjectAnimatoranimX = ObjectAnimator.ofFloat(myView, "x", 50f);
ObjectAnimatoranimY = ObjectAnimator.ofFloat(myView, "y", 100f);
AnimatorSetanimSetXY = new AnimatorSet();
animSetXY.playTogether(animX,animY);
animSetXY.start();
一个ObjectAnimator对象:
PropertyValuesHolderpvhX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolderpvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView,pvhX, pvyY).start();
ViewPropertyAnimator对象:
myView.animate().x(50f).y(100f);
在XML中声明动画
属性动画系统会让你用XML来声明属性动画,而不是用编程的方式来做它。通过XML中定义你的动画,能够更加容易的在多个Activity中重用动画,并且更加容易的编辑动画的播放顺序。
从Android3.1开始,要把使用新的属性动画的API的动画文件与那些使用传统的视图动画框架区分开,你应该把属性动画的XML文件保存在res/animator/目录中(而不是res/anim/)。animator目录名是可选的,但是如果想要使用Eclipse ADT插件(ADT11.0.0+)中的布局编辑器,就必须使用animator目录,因为ADT只搜索res/animator目录中属性动画资源。
以下是属性动画类在XML声明中所使用的对应的XML标签:
· ValueAnimator
- <animator>
· ObjectAnimator
- <objectAnimator>
· AnimatorSet
- <set>
以下示例顺序的播放两组对象动画,第一组动画中嵌套了一个同时播放两个对象的动画:
<setandroid:ordering="sequentially">
<set>
<objectAnimator
android:propertyName="x"
android:duration="500"
android:valueTo="400"
android:valueType="intType"/>
<objectAnimator
android:propertyName="y"
android:duration="500"
android:valueTo="300"
android:valueType="intType"/>
</set>
<objectAnimator
android:propertyName="alpha"
android:duration="500"
android:valueTo="1f"/>
</set>
为了运行这个动画,在代码中,必须把这个XML资源填充到一个AnimatorSet对象中,并且在开始播放这个动画集之前,要把这个动画集合设置给目标对象。调用setTarget()方法就可以方便的把AnimatorSet对象中的所有子对象设置给一个单一的目标对象。以下代码显示了做这件事的方法:
AnimatorSetset = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,R.anim.property_animator);
set.setTarget(myObject);
set.start();
有关定义属性动画的XML语法信息,请看“动画资源”。
http://developer.android.com/guide/topics/resources/animation-resource.html#Property
Android视图动画---View Animation
本文译自:http://developer.android.com/guide/topics/graphics/view-animation.html
你能够使用视图动画系统来执行View对象上的补间动画。补间动画是用诸如开始点、结束点、尺寸、旋转以及一些其他的动画特性来计算的动画。
补间动画能够在View对象的内容上执行一个简单的变换系列(位置、尺寸、旋转和透明度)。因此,如果有一个TextView对象,就能够移动、旋转、放大或缩小文本。如果该TextView对象有一个背景图片,那么这个背景图片会跟文本一起变换。animation包提供了补间动画中所使用的所有的类。
动画指令序列定义了补间动画,这些指令既可以用XML来定义,也可以用Android代码来定义。跟布局定义一样,推荐使用XML来定义动画,因为它更加可读、可重用、并且比应编码的动画更加可插拔。在下面的例子中,我们使用XML。(要学习更多的有关在应用程序代码中定义动画的知识,请阅读AnimationSet类和其他的Animation子类。)
动画指令定义了你想要的动画变换,以及动画发生的时机和动画的播放的时长。动画变换能够是顺序的或并发的,例如:有一个从左向右移动的TextView对象的内容,然后旋转180度,或者在文本移动的同时旋转。每种变换都需要一组参数来指定所要的变换(针对尺寸变换的开始尺寸和结束尺寸、针对旋转的开始角度和结束角度等等),以及一组共同的参数(例如,开始时间和持续时长)。如果要是让几种变换同时发生,就要给它们设置相同的开始时间;如果要让它们顺序播放,就要用开始时间加上前面动画变换的时长来计算下一个动画播放的开始时间。
动画XML文件要定义在你的Android工程的res/anim/目录中。这个文件必须要有一个单独的根元素:这个元素既可以是一个单独的<alpha>、<scal>、<translate>、<rotate>的插值元素,也可以是拥有这些元素(包括<set>元素)组合的<set>元素。默认情况下,所有的动画指令都是并发的。要让它们顺序的发生,就必须像下面的示例所示的那样,指定startOffset属性。
下面的XML来自于APIDemo中的一个用于拉伸,然后同时旋转的View对象:
<setandroid:shareInterpolator="false">
<scale
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="0.6"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false"
android:duration="700" />
<setandroid:interpolator="@android:anim/decelerate_interpolator">
<scale
android:fromXScale="1.4"
android:toXScale="0.0"
android:fromYScale="0.6"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="400"
android:fillBefore="false" />
<rotate
android:fromDegrees="0"
android:toDegrees="-45"
android:toYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:startOffset="700"
android:duration="400" />
</set>
</set>
在左上角屏幕的坐标(在上面的这个例子中没有使用)是(0,0),并且向右下角逐渐增加。
有一些值,如pivotX,能够相对于对象自己或它的父容器来指定。对于想要的值必须使用正确的格式(50是指相对它的父容器的左上角的50%,50%则是指相对于它自己的左上角的50%)。
通过分配一个Interpolator对象,能够决定如何随着时间的推移来进行一个动画的变换。Android包括了几种Interpolator子类,它们能够指定各种速度的曲线,例如:AccelerateInterpolator会告诉系统执行一个开始慢,然后逐渐加速的变换。每种变换都会有一个属性值被应用于XML中。
保存在工程的res/anim/目录中的hyperspace_jump.xml文件,下列代码会引用这个文件,并把它应用于一个来自布局的ImageView对象。
ImageViewspaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);
AnimationhyperspaceJumpAnimation = AnimationUtils.loadAnimation(this,R.anim.hyperspace_jump);
spaceshipImage.startAnimation(hyperspaceJumpAnimation);
作为startAnimation()方法的一个替代方法,你能够用Animation.setStartTime()方法来定义动画的开始时间,然后用View.setAnimation()方法把这个动画对象分配给View对象。
关于XML语法、可用的标签和属性的更多信息,请看“动画资源”(http://developer.android.com/guide/topics/resources/animation-resource.html)
注意:不管你的动画如何移动或调整尺寸,拥有动画的View对象的边界都不会自动的调整来适应变化,即使动画超出了View对象的边界也不会被裁剪,但是如果动画超出了它的父容器的的边界,那么它将会被裁剪。
Android绘图动画---DrawableAnimation
本文译自:http://developer.android.com/guide/topics/graphics/drawable-animation.html
绘图动画会让你依次的加载一系列的绘图资源来创建一个动画。这种动画是一种传统动画,它是用不同的图片序列来创建并依次播放的,看上去像放电影。AnimationDrawable类是绘图动画的基类。
你能够使用AnimationDrawable类的API在代码中定义动画的帧,但是,用一个单独的定义了组成动画帧的列表的XML来完成动画会更加简单。这种类型动画的XML文件要放在你的Android工程的res/drawable/目录中。这种情况下,指令是动画的播放顺序和每一帧动画的播放时间。
这个动画XML文件是由一个<animation-list>根元素和一系列的定义每一帧的<item>子元素组成。<item>元素定义了每一帧的绘图资源和播放时长。以下是绘图动画的一个示例XML文件:
<animation-listxmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">
<itemandroid:drawable="@drawable/rocket_thrust1"android:duration="200" />
<itemandroid:drawable="@drawable/rocket_thrust2"android:duration="200" />
<itemandroid:drawable="@drawable/rocket_thrust3"android:duration="200" />
</animation-list>
这个动画只有三个帧。通过把第一帧动画的android:oneshot属性设置为true,让动画播放一次,然后在最后一帧停止。如果它被设置为false,那么动画将会循环播放。使用这个保存在工程的res/drawable/目录中的rocket_thrust.xml文件,能够把一个背景图片添加到一个View对象上,然后播放动画。下面示例的Activity动画中添加了一个ImageView对象,并且在屏幕被触摸时动画开始播放:
AnimationDrawablerocketAnimation;
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageViewrocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
rocketAnimation= (AnimationDrawable) rocketImage.getBackground();
}
publicboolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
rocketAnimation.start();
returntrue;
}
returnsuper.onTouchEvent(event);
}
注意,在Activity的onCreate()方法执行期间,不能调用AnimationDrawable对象上的start()方法,这是至关重要的,因为AnimationDrawable对象在这时还没有跟窗口绑定。如果要立即播放动画,不需要交互,你可以在Activity的onWindowFocusChanged()回调方法中调用star()方法,onWindowFocusChanged()方法会在窗口获取焦点时被Android系统调用。
关于XML语法、可用的标签属性的更多信息,请看“动画资源”(http://developer.android.com/guide/topics/resources/animation-resource.html)