Android动画学习笔记-Android 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有两个步聚:

  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中的函数都定义了一个空函数体,这样我们就只用定义想监听的事件而不用实现每个函数却只定义一空函数体。

复制代码

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(驼峰命名法)

  • 如上面的例子中,像ofFloat之类的工场方法,第一个参数为对象名,第二个为属性名,后面的参数为可变参数,如果values…参数只设置了一个值的话,那么会假定为目的值,属性值的变化范围为当前值到目的值,为了获得当前值,该对象要有相应属性的getter方法:get

  • 如果有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,当有子元素可见性改变时(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.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一个PropertyValuesHolder对象,然后通过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: 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动画

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-MhBfTGVH-1715030484227)]

[外链图片转存中…(img-vn3l0Dqs-1715030484228)]

[外链图片转存中…(img-UZZMlzDI-1715030484228)]

[外链图片转存中…(img-cuQydOw1-1715030484228)]

[外链图片转存中…(img-BYHH6e3I-1715030484228)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值