`

Android动画入门一---总体概述

 
阅读更多
3.0以前,android支持Tween animation和Frame animation,3.0以后,又引入了Property animation。这三种动画模式在SDK中被称为Property animation,View animation(Tween animation),Drawable animation(Frame animation)。
1. View Animation(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中的定义方式如下:
<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属性当触发动画时不行。
  2),  在动画start()之前要先stop(),不然在第一次动画之后会停在最后一帧,这样动画就只会触发一次。
  3),  最后一点是SDK中提到的,不要在onCreate中调用start,因为AnimationDrawable还没有完全跟Window相关联,如果想要界面显示时就开始动画的话,可以在onWindowFoucsChanged()中调用start()。


3. Property Animation


属性动画:
它更改的是对象的实际属性,在View Animation(Tween Animation)中,其改变的是View的绘制效果,真正的View的属性保持不变,比如无论你在对话中如何缩放Button的大小,Button的有效点击区域还是没有应用动画时的区域,其位置与大小都不变。而在Property Animation中,改变的是对象的实际属性,如Button的缩放,Button的位置与大小属性值都改变了。而且Property Animation不止可以应用于View,还可以应用于任何对象。Property Animation只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的。
在Property Animation中,可以对动画应用以下属性:

    Duration:动画的持续时间
    TimeInterpolation:属性值的计算方式,如先快后慢
    TypeEvaluator:根据属性的开始、结束值与TimeInterpolation计算出的因子计算出当前时间的属性值
    Repeat Country and behavoir:重复次数与方式,如播放3次、5次、无限循环,可以此动画一直重复,或播放完时再反向播放
    Animation sets:动画集合,即可以同时对一个对象应用几个动画,这些动画可以同时播放也可以对不同动画设置不同开始偏移
    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即为时间因子):
(Math.cos((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);
    }

参数分别为上一步的插值因子,开始值与结束值。
3.2 ValueAnimator
ValueAnimator包含Property Animation动画的所有核心功能,如动画时间,开始、结束属性值,相应时间属性值计算方法等。应用Property Animation有两个步聚:

    计算属性值
    根据属性值执行相应的动作,如改变对象的某一属性。

  ValuAnimiator只完成了第一步工作,如果要完成第二步,需要实现ValueAnimator.onUpdateListener接口,如:
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()

onAnimationCancel()

ValueAnimator.AnimatorUpdateListener
onAnimationUpdate()  //通过监听这个事件在属性的值更新时执行相应的操作,对于ValueAnimator一般要监听此事件执行相应的动作,不然Animation没意义(可用于计时),在ObjectAnimator(继承自ValueAnimator)中会自动更新属性,如无必要不必监听。在函数中会传递一个ValueAnimator参数,通过此参数的getAnimatedValue()取得当前动画属性值。

可以继承AnimatorListenerAdapter而不是实现AnimatorListener接口来简化操作,这个类对AnimatorListener中的函数都定义了一个空函数体,这样我们就只用定义想监听的事件而不用实现每个函数却只定义一空函数体。

ObjectAnimator oa=ObjectAnimator.ofFloat(tv, "alpha", 0f, 1f);
oa.setDuration(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有一定的限制,要想使用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) {
    ObjectAnimator oa=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.5 TypeEvalutors
根据属性的开始、结束值与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();
        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中的子元素可以通过setVisibility使其Visible、Invisible或Gone,当有子元素可见性改变时,可以向其应用动画,通过LayoutTransition类应用此类动画:

transition.setAnimator(LayoutTransition.DISAPPEARING, customDisappearingAnim);

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

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

  第二个参数为一Animator。

mTransitioner.setStagger(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.setDuration(2000);

复制代码

  上述代码的意思为:设置btn对象的width属性值使其:

    开始时 Width=400
    动画开始1/4时 Width=200
    动画开始1/2时 Width=400
    动画开始3/4时 Width=100
    动画结束时 Width=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后再改变参数invalidate,这样虽然View的大小或旋转角度等改变了,但View的实际属性没变,所以有效区域还是应用动画之前的区域,比如你把一按钮放大两倍,但还是放大这前的区域可以触发点击事件。为了改变这一点,在Android 3.0中给View增加了一些参数并对这些参数增加了相应的getter/setter函数(ObjectAnimator要用这些函数改变这些属性):

    translationX,translationY:转换坐标(control where the View is located as a delta from its left and top coordinates which are set by its layout container.)
    rotation,rotationX,rotationY:旋转,rotation用于2D旋转角度,3D中用到后两个
    scaleX,scaleY:缩放
    x,y:View的最终坐标(utility properties to describe the final location of the View in its container, as a sum of the left and top values and translationX and translationY values.)
    alpha:透明度

  跟位置有关的参数有3个,以X坐标为例,可以通过getLeft(),getX(),getTranslateX()获得,若有一Button btn2,布局时其坐标为(40,0):
//应用动画之前
btn2.getLeft();    //40
btn2.getX();    //40
btn2.getTranslationX();    //0
//应用translationX动画
ObjectAnimator oa=ObjectAnimator.ofFloat(btn2,"translationX", 200);
oa.setDuration(2000);
oa.start();
/*应用translationX动画后
btn2.getLeft();    //40
btn2.getX();    //240
btn2.getTranslationX();    //200
*/
//应用X动画,假设没有应用之前的translationX动画
ObjectAnimator oa=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.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);
  • 大小: 35.2 KB
  • 大小: 41.2 KB
  • 大小: 41 KB
分享到:
评论

相关推荐

    Android入门手册-中文版

    根据给定的“Android入门手册-中文版”的文件信息,我们可以从中提炼出一系列与Android开发相关的知识点,这些知识点覆盖了从Android系统的基本概念到实际应用开发的各个环节。下面,我们将详细解析这些知识点。 ##...

    android入门-课程介绍

    【Android入门课程介绍】 在数字化世界中,Android操作系统占据着移动设备市场的主导地位,因此学习Android开发成为许多...无论你是零基础的新手,还是希望转行至Android开发的程序员,这都将是一次宝贵的入门之旅。

    Android用户接口开发入门手册-英文版

    这份"Android用户接口开发入门手册"英文版为开发者提供了一个深入理解Android UI设计和实现的基础教程。以下是对该手册内容的详细概述: 1. **Android UI体系结构**:Android UI基于组件驱动的模型,主要包括...

    Android入门到精通详解(完整书签)

    综上所述,《Android入门到精通详解》一书全面覆盖了Android应用程序开发的各个方面,从基础知识到高级技巧都有详细介绍。无论是初学者还是有经验的开发者都能从中受益,掌握开发高质量Android应用程序所需的技能。

    Android从入门到精通(PPT)

    一、Android系统概述 Android是由Google主导的开源操作系统,广泛应用于智能手机和平板电脑。它基于Linux内核,提供了丰富的API和工具,让开发者能够创建功能强大的移动应用。在PPT中,这部分可能会介绍Android系统...

    android从入门到精通ppt

    2. Android动画:了解帧动画、属性动画以及视图动画的使用。 3. 耗时操作优化:处理大图片、内存泄漏、后台服务优化等。 通过这套《Android从入门到精通》教程,你将系统地学习Android开发,从基础知识到高级特性,...

    Android开发入门书籍

    ### Android开发入门知识点详解 #### 一、核心概念(Part I: Core Concepts) **1.1 大局观(Chapter 1: The Big Picture)** - **知识点:** - Android平台简介 - Android应用架构 - 应用组件(Activity、...

    Android 4游戏编程入门经典

    #### 一、书籍概述 《Android 4游戏编程入门经典》这本书是为那些希望在Android平台上开发游戏的新手准备的全面指南。本书覆盖了从Android基础知识到游戏开发高级技巧的所有内容,并通过实际案例帮助读者掌握所需...

    android从入门到精通详解

    知识点1:Android系统概述 ...以上知识点是文档中所涵盖的核心内容,不仅包括了Android开发的基础知识,还涵盖了在开发过程中需要关注的高级应用,为刚学习Android开发的初学者提供了一条从入门到精通的学习路径。

    Android Recipes A Problem-solution Approach 4th Edition

    1. **书籍概述**:本书为Android开发提供了一系列实用的问题解决方法,适用于那些希望快速找到解决问题方案的开发者。 2. **章节内容**:书中分为八个章节,涵盖了从基本布局到高级系统交互的各种主题。 3. **技术...

    Beginning Android Games( Android 游戏开发入门)

    ### Android游戏开发入门知识点概述 #### 一、书籍基本信息及适用人群 - **书籍名称**:《Beginning Android Games》(Android游戏开发入门) - **作者**:Mario Zechner - **出版信息**:Apress出版社,2011年4月...

    Android 应用开发入门教程(经典版)

    【Android 应用开发入门教程】是一份详细指导初学者入门Android应用开发的经典教程,涵盖了Android系统的结构、SDK的使用,以及应用程序的开发流程。在系统介绍中,讲解了Android作为一个开源移动操作系统的概述,...

    新版Android开发教程;笔记--基础入门二

    在Android开发领域,基础知识是构建复杂应用的基石。...然而,Android开发是一个不断进阶的过程,继续探索更高级的主题,如存储管理、网络编程、动画和第三方库的使用,将有助于你成为一名出色的Android开发者。

    Android入门到精通

    ### Android入门到精通知识点...综上所述,《Android入门到精通》这本书全面介绍了Android系统的各个方面,从系统结构、SDK使用到应用程序的开发和UI实现,再到2D/3D图形编程,为初学者提供了一个系统的学习路线图。

    ANDROID从入门到精通 pdf

    #### 一、Android概述 ##### 1.1 什么是Android Android是一种基于Linux内核(不包含GNU组件)的开源移动操作系统,由Google公司和开放手机联盟领导及开发。Android主要应用于移动设备,如智能手机和平板电脑等。 ...

    Android Recipes - A Problem-Solution Approach

    通过这个案例,读者可以学习到如何在Android平台上使用OpenGL ES进行图形渲染、动画制作、碰撞检测等一系列关键技术。此外,还将了解到如何优化游戏性能以获得流畅的用户体验。 综上所述,《Android Recipes: A ...

Global site tag (gtag.js) - Google Analytics