Android 动画详解:属性动画、View 动画和帧动画

 前言

Android动画是面试的时候经常被问到的话题。我们都知道Android动画分为三类:View动画、帧动画和属性动画。

先对这三种动画做一个概述:

View动画是一种渐进式动画,定义动画开始和结束的两帧,并指定动画变化的时间和方式。并通过平移、缩放、旋转和透明度四种效果结合成复杂的动画效果。而在开始和结束帧之间插入的渐变值依据的是插值器。

帧动画是通过不停的切换图片实现动画效果。

属性动画是不停的改变对象的属性来实现动画效果。4.4新出的过渡动画只是对属性动画的一层封装。

本文原创,转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52724655

1.  View动画  

1.1 系统提供的四种View动画(补间动画)

View动画可以在res/anim/name.xml文件里进行配置,四种View动画的渐变式变换分别对应<translate>、<scale>、<rotate>、<alpha>四个标签,动画集合可以使用<set>标签。xml的各个动画属性比较简单,这里就不再贴实例代码了。只需要注意如何应用配置好的xml文件来启动动画即可:

view.startAnimation(AnimationUtils.loadAnimation(this,R.anim.myanimation));

这些当然也可以在Java代码里进行配置,也比较简单,这里写了一个示例代码:

splash = (RelativeLayout)findViewById(R.id.splash);

//旋转动画

RotateAnimation rotateAnimation =newRotateAnimation(0,360,

Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);

rotateAnimation.setDuration(2000);

rotateAnimation.setFillAfter(true);

//缩放动画

ScaleAnimation scaleAnimation =newScaleAnimation(0,1,0,1,

Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);

scaleAnimation.setDuration(2000);

scaleAnimation.setFillAfter(true);

//渐变动画

AlphaAnimation alphaAnimation =newAlphaAnimation(0.2f,1.0f);

alphaAnimation.setDuration(2000);

alphaAnimation.setFillAfter(true);

//平移动画

TranslateAnimation translateAnimation = newTranslateAnimation (0,0,100,100);

translateAnimation.setDuration(2000);

translateAnimation.setFillAfter(true);

//动画集合

AnimationSet animationSet =newAnimationSet(true);

animationSet.addAnimation(rotateAnimation);

animationSet.addAnimation(scaleAnimation);

animationSet.addAnimation(alphaAnimation);

animationSet.addAnimation(translateAnimation);

//启动动画

plash.startAnimation(animationSet);

1.2   自定义View动画

实际项目中,如果四种基本动画无法满足需求,就需要自定义补间动画了。

完成自定义动画需要继承Animation类,并重写其initialize()以及applyTransformation()。前者用于一些初始化的操作,后者用于进行矩阵变换。

1.3     为ViewGroup的所有子元素设置动画

上面1.1,1.2都是给View设置动画效果,Android同样提供了为ViewGroup设置android:layoutAnimation=”@anim/layout_anim”来达到给ViewGroup中所有子元素设置动画的目的。下面给出相关代码:

//res/anim/anim/layout_anim.xml

android:delay=”0.1”//动画延迟时间为0.1*T,本例为100ms

android:animationOrder=”normal”//子元素的播放动画顺序为顺序,也有reverse以及random

android: animation=”@anim/layout_anim_item”/>

//res/anim/anim/layout_anim_item.xml


animation:duration=”200”//每个子元素的动画周期T

animation:interpolator=”@android:anim/accelerate_ interpolator”//指定插值器

animation:shareInterpolator=”true”>//表示所有子元素共享该插值器

</set>

1.4     为Activity切换设置动画

估计大家也都用过,在startActivity()之后使用,使Activity切换时达到一个平移的动画效果:

overridePendingTransition(R.anim.tran_in,R.anim.tran_out);

//res/anim/tran_in


android:duration="500"

//表示从屏幕100%的位置开始,因此tran_out当然是toXDelta="-100%p",其他不变

android:fromXDelta="100%p"

android:fromYDelta="0"

android:toXDelta="0"

android:toYDelta="0">

</translate>

2.   帧动画

上面也提到了,帧动画就是不停的切换图片实现动画效果。很明显容易OOM,所以使用帧动画要注意图片大小。

帧动画的使用也很简单,使用示例如下:

//res/drawable/myanimation.xml


animation:oneshot=”false” >//false为循环播放,true为类似于View动画的setFillAfter效果

</animation-list>

//在代码里加载动画设置并启动动画

view.setBackgroundResource(R.drawable.myanimation.xml);

(AnimationDrawable)view.getBackground.start();

3. 属性动画

View动画的那四种效果有很明显的缺点,绘制出来的效果其实并没有真正改变View的属性,即left、top、right和bottom的值,只是系统临时绘制的结果。这样View的点击位置并没有发生变化。针对这个问题,从Android3.0开始属性动画应运而生。

属性动画本质是通过改变新增的属性(如平移translationX/Y、缩放scaleX/Y、旋转rotationX/Y等)并刷新屏幕来实现动画效果,并且实现点击位置的实时改变。但是属性动画仍然不会修改原始的上下左右四个值。最后需要注意的是,属性动画不止用于View,还可以用于任何对象。

下面介绍与属性动画相关的类和方法:


3.1  setTranslationX方法

该方法直接更改view属性的方法,因为有时候不需要使用动画效果。

view.setTranslationX(x);//3.0以后

ViewHelper.setTranslationX(view,x);//3.0以前通过NineOldAndroid库实现

3.2   ValueAnimator类

ValueAnimator只定义和执行动画流程,并没有直接操作属性值的逻辑,需要添加动画更新的监听,并在onAnimationUpdate()中执行自定义的动画逻辑。

ValueAnimator animator = ValueAnimator.ofInt(1,100);//定义动画,相当于1秒内数100个数

animator.addUpdateListener(newAnimatorUpdateListener() {

@Override

publicvoidonAnimationUpdate(ValueAnimator animation){

floatfraction = animation.getAnimatedFraction();//动画进度值0-1

//整型估值器帮我们计算了start+(end-strat)*fraction,并设置给控件的宽度

view.getLayoutParams().width =newIntEvaluator().evaluate(fraction,start,end)//不需要set方法

        view.requestLayout();

    }

});

animator.setDuration(1000).start();

3.3    ObjectAnimator类

ObjectAnimator继承自ValueAnimator,它允许直接改变view的属性,下面通过一个例子介绍。

//x轴方向缩放的例子

ObjectAnimator animator = ObjectAnimator.ofFloat(view,”scaleX”,2.0f);

animator.setDuration(1000);

animator.setStartDelay(1000);

animator.start();

大多数的情况使用ObjectAnimator就足够了,因为它不用像ValueAnimator那样自己写动画更新的逻辑,但是ObjectAnimator有一定的限制——它需要目标属性提供指定的处理方法(譬如提供get/set方法),这是因为ObjectAnimator的原理是不停的调用set方法更新属性值,并且如果我们没有传递初始值,系统会直接调用get方法获取值。而上面3.2中介绍过的ValueAnimator则不直接操作属性值,所以要操作对象的属性可以不需要se/get方法,你完全可以通过当前动画的计算去修改任何属性。

针对这个问题,官方推荐我们用一个类包装原始对象,间接为其提供get/set方法,实现起来很简单,实例如下:

ViewWrapper wrapper =newViewWrapper(view);

ObjectAnimator.ofInt(wrapper,”width”,200).setDuration(1000).start();

private   static    class   ViewWrapper{

private  View myView;

public   View  Wrapper(View view){

      myView = view;

    }

public  int   getWidth(){

returnmyView.getLayoutParams().width;

    }

public   int  setWidth(intwidth){

      myView.getLayoutParams().width = width;

      myView.requestLayout();

    }

}

3.4  ViewPropertyAnimation类

ViewPropertyAnimation是NineOldAndroid库中的类,简化了ObjectAnimator类的操作,并且NineOldAndroid库兼容了3.0以前的Android版本。下面经过一个例子介绍。

//x轴方向缩放的例子,效果同3.3

ViewPropertyAnimation.animate(view).scaleX(2.0f).setDuration(1000)

.setInterpolator(newOvershootInterpolator())

.setStartDelay(1000).start();

3.5  AnimationSet类

动画集合,提供把多个动画组合成一个组合的机制,并可设置动画的时序关系,如同时播放、顺序播放或延迟播放。具体使用方法比较简单,如下所示:

ObjectAnimator objectAnimator1= ObjectAnimator.ofFloat(view,"alpha",1.0f,0f);

ObjectAnimator objectAnimator2= ObjectAnimator.ofFloat(view,"translationY",0f,30f);

ObjectAnimator objectAnimator3= ObjectAnimator.ofFloat(view,"translationX",0f,30f);

AnimatorSet animatorSet =newAnimatorSet();

animatorSet.setDuration(5000);

animatorSet.setInterpolator(newLinearInterpolator());

// animatorSet.playTogether(objectAnimator1, objectAnimator2. objectAnimator3); //三个动画同时执行 

// 12同时执行,3接着执行

animatorSet.play(objectAnimator1).with(objectAnimator2); 

animatorSet.play(objectAnimator3).after(objectAnimator2); 

animatorSet.start();

4. 插值器总结

4.1 系统已经提供给我们的插值器

各种插值器都是实现了Interpolator接口,下面来看一下系统已经提供给我们直接使用的插值器。


4.2  自定义插值器

Interpolator都实现了Interpolator接口,而Interpolator接口又继承自TimeInterpolator,TimeInterpolator接口定义了一个由系统调用的getInterpolation(float input)方法,其中参数input代表动画完成进度,在0和1之间。我们自定义插值器只需要实现Interpolator接口并覆写getInterpolation()方法即可实现自定义的动画效果。


如下就是一个动画始末速率较慢、中间加速的AccelerateDecelerateInterpolator插值器:

public   class    AccelerateDecelerateInterpolator    extends   BaseInterpolator

implements        NativeInterpolatorFactory{

    ......

public       float      getInterpolation(floatinput){

return(float)(Math.cos((input +1) * Math.PI) /2.0f) +0.5f;

    }

    ......

}

5. 动画监听器

我们在平时开发过程中,经常要监听动画完成的时机以继续业务逻辑,那么我们可以通过给动画集合设置AnimationListener监听器来实现。分别可以监听动画开始、结束、取消以及重复播放。

//监听动画完成

animationSet.setAnimationListener(newAnimation.AnimationListener() {

@Override

publicvoidonAnimationStart(Animation animation){}

@Override

public    void     onAnimationEnd(Animation animation){}

@Override

public    void     onAnimationRepeat(Animation animation){}

@Override

public    void     onAnimationCancel(Animation animation){}

});

最后若想监听动画中每一帧的回调,我们可以设置AnimatorUpdateListener监听器并重写其onAnimationUpdate()方法即可。

至此关于Android动画的知识总结完毕。

转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52724655

想对作者说点什么? 我来说一句

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,825评论 4 377
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,887评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,425评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,801评论 0 224
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,252评论 3 299
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,089评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,216评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 31,005评论 0 215
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,747评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,883评论 2 255
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,354评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,694评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,406评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,222评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,242评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,017评论 2 281

推荐阅读更多精彩内容