Android 动画

来源:互联网 发布:贵州广电网络电话多少 编辑:程序博客网 时间:2024/06/16 04:36

3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中又引入了一个新的动画系统:property animation,这三种动画模式在SDK中被称为property animation,view animation,drawable animation。 

1.View Animation(Tween Animation)

View Animation(Tween Animation):补间动画,给出两个关键帧,通过一些算法将给定属性值在给定的时间内在两个关键帧间渐变。
View animation只能应用于View对象,并只改变View对象绘制的位置,而没有改变View对象本身。它只支持一部分属性,如缩放旋转移动透明度,不会变背景颜色。可以代码定义,也可以用XML定义。可以给一个View同时设置多个动画,也可以在一个完成之后开始另一个。
用XML定义的动画放在/res/anim/文件夹内,XML文件的根元素可以为<alpha>,<scale>,<translate>,<rotate>,interpolator元素或<set>(表示以上几个动画的集合,set可以嵌套)。
默认情况下,所有动画是同时进行的。
startOffset属性:设置各个动画的开始开始时间来达到动画顺序播放的效果。
定义好动画的XML文件后,可以通过类似下面的代码对指定View应用动画。
ImageView iv = (ImageView)findViewById(R.id.iv);Animation anim =AnimationUtils.loadAnimation(this, R.anim.anim_scale);iv.startAnimation(anim);

2.Drawable Animation(Frame Animation)

Drawable Animation(Frame Animation):帧动画,就像GIF图片,通过一系列Drawable依次显示来模拟动画的效果。在XML中的定义方式如下:
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="true">    <item android:drawable="@drawable/iv1" android:duration="200" />    <item android:drawable="@drawable/iv2" android:duration="200" />    <item android:drawable="@drawable/iv3" android:duration="200" /></animation-list>
示例:
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);        setContentView(R.layout.main);        iv = (ImageView) findViewById(R.id.iv);        iv.setBackgroundResource(R.drawable.drawable_anim);        anim = (AnimationDrawable) iv.getBackground();    }    public boolean onTouchEvent(MotionEvent event) {        if (event.getAction() == MotionEvent.ACTION_DOWN) {            anim.stop();            anim.start();            return true;        }        return super.onTouchEvent(event);    }


       SDK里讲,AnimationDrawable还没有完全跟Window相关联,如果想要界面显示时就开始动画的话,可以在onWindowFoucsChanged()中调用start()方法。

3.Property Animation

Property Animation只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的。在Property Animation中,可以对动画应用以下属性:
Duration:动画的持续时间。
TimeInterpolation:属性值的计算方式,如先快后慢。
TypeEvaluator:根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值。
Repeat Country and behavior:重复次数与方式,如播放3次、5次、无限循环,可以此动画一直重复,或播放完时再反向播放。
Animation sets:动画集合,即可以同时对一个对象应用几个动画,这些动画可以同时播放也可以对不同动画设置不同开始偏移。
Frame refreash delay:多少时间刷新一次,即每隔多少时间计算一次属性值,默认为10ms,最终刷新时间还受系统进程调度与硬件的影响。

3.1Property Animation的工作方式

ValueAnimator即表示一个动画,包含动画的开始值x,结束值x,持续时间t等属性。
ValueAnimator里封装了一个TimeInterpolator,TimeInterpolator定义了属性值在开始值与结束值之间的插值方法。
ValueAnimator里封装了一个TypeAnimator,根据开始、结束值与TimeIniterpolator计算得到的值计算出属性值(pixel)
时间的百分比:input
动画已进行的时间:Math.cos((input+1)*Math.PI)
动画总时间:2.0f
时间因子:Math.cos((input+1)*Math.PI)/2.0f
插值因子:fraction = Math.cos((input+1)*Math.PI)/2.0f +0.5f     (TimeInterpolator时间插值因子)
属性值(pixel)的式求值程序(Type Evaluator)的计算方法是:
public Float evalurate(float fraction, Number startValue, Number endValue){float startFloat = startValue.floatValue();float endFloat = endValue.floatValue();return startFloat + fraction(endFloat - startFloat);}
参数分别为上一步的差值因子,开始值(pixel)与结束值(pixel)。

3.2 ValueAnimator

ValueAnimator包含Property Animation动画的所有核心功能,如动画时间,开始、结束属性值,相应时间属性值计算方法等。应用Property Animation有两个步聚:
  1. 计算属性值
  2. 根据属性值执行相应的动作,如改变对象的某一属性。
ValuAnimiator只完成了第一步工作,如果要完成第二步,需要实现ValueAnimator.onUpdateListener接口,如:
 ValueAnimator.ofFloat(0f, 1f); animator.setDuration(1000); animator.addUpdateListener(new AnimatorUpdateListener() {     public void onAnimationUpdate(ValueAnimator animation) {         Log.i("update", ((Float) animation.getAnimatedValue()).toString());         //通过监听这个事件在属性值更新时执行相应操作,对于ValueAnimator一般要监听此事件执行相应的动作。     } }); animator.setInterpolator(new CycleInterpolator(2)); animation.start();
Animator.AnimatorListener
onAnimationStart()onAnimationEnd()onAnimationRepeat()onAnimationCancel
可以继承AnimatorListenerAdapter而不是实现AnimatorListener接口来简化操作,这个类对AnimatorListener中的函数都定义了一个空函数体,这样我们就定义想监听的事件,只定义一空函数体。不用实现每个函数。    
以下是把一个TextView的透明度在1秒内从0变至1。
ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "alpha", 0f, 1f);animator.setDuration(1000);animator.addListener(new AnimatorListenerAdapter(){    public void on AnimationEnd(Animator animation){        Log.i("Animation","end");    }});oa.start();

3.3 ObjectAnimator

继承自ValueAnimator,要指定一个对象及该对象的一个属性,完成了Property Animation的全部两步操作。实际应用中一般都会用ObjectAnimator来改变某一对象的某一属性,但用ObjectAnimator有一定的限制,要想使用ObjectAnimator,应该满足以下条件:
  • 对象应该有一个setter函数:set<PropertyName>(驼峰命名法)
  • 如上面的例子中,像ofFloat之类的工场方法,第一个参数为对象名,第二个为属性名,后面的参数为可变参数,如果values…参数只设置了一个值的话,那么会假定为目的值,属性值的变化范围为当前值到目的值,为了获得当前值,该对象要有相应属性的getter方法:get<PropertyName>
  • 如果有getter方法,其应返回值类型应与相应的setter方法的参数类型一致。

  如果上述条件不满足,则不能用ObjectAnimator,应用ValueAnimator代替。

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

根据属性的开始值(pixel)、结束值(pixel)与TimeInterpolation计算出的因子计算出当前时间的属性值,android提供了以下几个evalutor(求值程序):
IntEvaluator:属性的值类型为int;
FloatEvaluator:属性的值类型为float;
ArgbEvaluator:属性的值类型为十六进制颜色值;
TypeEvaluator:一个接口,可以通过实现该接口自定义Evaluator。
自定义TypeEvalutor很简单,只需要实现一个方法,如FloatEvalutor的定义:
public class FloatEvaluator implements TypeEvaluator {    public Object evaluate(float fraction, Object startValue, Object endValue) {        float startFloat = ((Number) startValue).floatValue();        float endFloat = ((Number)startValue).floatValue();        return startFloat + fraction * (endFloat - startFloat);    }}
根据动画执行的时间跟应用的Interpolator,会计算出一个0~1之间的因子,即evalute函数中的fraction参数。

3.6 TimeInterpolator

time interpolator定义了属性值变化的方式,如线性均匀改变,先慢后渐快等。在Property Animation中是TimeInterpolator,在View Animation中是Interpolator,这两个是一样的,在3.0之前只有Interplator,3.0之后实现代码转移至了TimeInterplator。Interpolator继承自TimeInterpolator,内部没有任何其他代码。
AccelerateInterpolator          加速
DecelerateInterpolator         减速
AccelerateDecelerateInterolator    先加速后减速
AnticipateInterpolator        反向加速
AnticipateOvershootInterpolator    反向加超越,先向相反方向改变,再加速播放超出目的值,后缓慢移动至目的值。
BounceInterpolator         跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100
CycleInterpolator          循环,动画循环一定次数,值的改变为一正弦函数:Math.sin(2 * mCycles * Math.PI * input)
LinearInterpolator          线性
OvershottInterpolator        超越,超出目的值的播放速度后缓慢改变到目的值
TimeInterpolator          一个接口,允许你自定义interpolator,以上几个都是实现了这个接口

3.7 当Layout改变时应用动画

ViewGroup中的子元素可以通过setVisibility使其Visible、Invisible或Gone,当有子元素的可见性改变时,可以向其应用动画,通过LayoutTransition类应用此类动画:
transitioner.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeDisappearingAnim);

通过setAnimator应用动画,第一个参数表示应用的情境,可以以下4种类型:

  • APPEARING        当一个元素变为Visible时对其应用的动画
  • CHANGE_APPEARING   当一个元素变为Visible时,因系统要重新布局有一些元素,则需要移动的元素应用的动画
  • DISAPPEARING      当一个元素变为InVisible时对其应用的动画
  • CHANGE_DISAPPEARING 当一个元素变为Gone时,因系统要重新布局有一些元素,则需要移动的元素应用的动画 disappearing from the container.

  第二个参数为一Animator。

transitioner.setStagger(LayoutTransition.CHANGE_APPEARING, 10);
此函数设置动画持续时间,参数分别为类型与时间。

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 kf3 = Keyframe.ofInt(0.75f, 100);Keyframe kf4 = Keyframe.ofInt(1f, 500);PropertyValuesHolder propertyValues = PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2, kf3, kf4);ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(btn, pvhRotation);objectAnimator.setDuration(2000);objectAnimator.start();
上述代码的意思是:设置btn对象的width属性值随时间的变化而变化,先后是400,200,400,100,500。
第一个参数是时间百分比,第二个参数是该时间对应的属性值。
定义了一些Keyframe后,通过PropertyValuesHolder类的方法ofKeyframe封装,然后通过ObjectAnimator.ofPropertyValuesHolder获得Animator。
下面的代码可以实现同样的效果:
ObjectAnimator oa=ObjectAnimator.ofInt(btn2, "width", 400,200,400,100,500);oa.setDuration(2000);oa.start();

3.9 Animating Views

在View Animation中,对View应用Animation并没有改变View的属性,动画的实现是通过其Parent View实现的,在View被drawn时Parents View改变它的绘制参数,draw后改变参数无效,这样虽然View的大小或旋转角度等改变了,但view的实际属性没变,所以有效区还是应用动画之前的区域。为了改变这一点,在Android3.0中给View增加了一些参数并对这些参数怎机啊了相应的getter/setter函数(ObjectAnimator要用这些函数改变这些属性):
translationX,translationY:转换坐标(control where the View is Located as a delta from its left androi top coordinates which are set by its layout container.)
rotation,rotationX,rotationY:旋转,rotation用于2D旋转角度,3D中用到后两个。
scaleX,scaleY:缩放
x,y:View的最终坐标
alpha:透明度

跟位置有关的参数有3个,以X坐标为例,可以通过getLeft(),getX(),getTranslateX()获得,若有一个Button按钮,布局时坐标为(30,0):
Button btn = (Button) findViewById(R.id.btn);btn.getLeft();//30btn.getX();//30btn.getTranslationX();//0ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(btn, "translationX", 200);objectAnimator.setDuration(1000);objectAnimator.start();btn.getLeft();//30btn.getX();//230btn.getTranslationX();//200ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(btn,"x",200);objectAnimator2.setDuration(1000);objectAnimator2.start();btn.getLeft();//30btn.getX();//200btn.getTranslationX();//170
无论怎样应用动画,原来的布局时的位置通过getLeft()获得,保持不变;
X是View最终的位置;
对于X动画,源代码是这样的:
case X:       info.mTranslationX = value - mView.mLeft;       break;
Property Animation也可以在XML中定义
  • <set> - AnimatorSet
  • <animator> - ValueAnimator
  • <objectAnimator> - ObjectAnimator
XML文件应放大/res/animator/中,通过以下方式应用动画:
AnimatorSet animatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.anim.property_animator);animatorSet.setTarget(myObject);animatorSet.start();

3.10 ViewPropertyAnimator

如果需要对一个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);

0 0
原创粉丝点击