图文详解Android属性动画

  • 格式:pdf
  • 大小:174.17 KB
  • 文档页数:6

图⽂详解Android属性动画

Android中的动画分为视图动画(View Animation)、属性动画(Property Animation)以及Drawable动画。从Android 3.0(API

Level 11)开始,Android开始⽀持属性动画,本⽂主要讲解如何使⽤属性动画。关于视图动画可以参见博⽂《Android四⼤视

图动画图⽂详解》。

⼀、概述

视图动画局限⽐较⼤,如下所述:

1、视图动画只能使⽤在View上⾯。

2、视图动画并没有真正改变View相应的属性值,这导致了UI效果与实际View状态存在差异,并导致了⼀系列怪异⾏为,⽐

如在使⽤了视图动画TranslateAnimation的View的UI上对其触摸,你可能惊讶地发现并没有触发触摸事件。

鉴于视图动画以上缺陷,从Android 3.0引⼊了属性动画。属性动画具有以下特性:

1、属性动画应⽤⾯更⼴,不仅仅应⽤于View,可以将其应⽤到任意的对象上⾯,且该对象不需要具有UI界⾯。

2、当将属性动画作⽤于某个对象时,可以通过调⽤对象的setXXX⽅法实际改变对象的值。所以,当将属性动画作⽤于某个

View时,View对象对应的属性值会被改变。我们看⼀下属性动画时如何⼯作的。

其实属性动画的⼯作原理并不复杂,假设⼀个对象有⼀个属性x,我们想通过属性动画动态更改该值,假设我们想在40ms内将

x的值从0渐变到40,那么如下图所⽰:

随着时间的增长,对应的x值也相应地线性渐变,当动画完成时,x的值就是我们设置的最终值40。如果x值线性渐变,那么x

的变化速度就是匀速的。其实,我们也可以变速地改变x的值,这会我们可以⼀开始加速增加x的值,后⾯减速增加x的值,如

下图所⽰:

如上图所⽰,在前20ms,x值加速增⼤,在后20ms,x值增⼤的速度降低。

其实,每种改变x值速度的⽅式都叫做时间插值器TimeInterpolator,第⼀张图中使⽤的时间插值器叫做LinearInterpolator,第⼆

张图中使⽤的时间插值器叫做AccelerateDecelerateInterpolator。动画开始后,时间插值器会根据对应的算法计算出某⼀时刻

x的值,然后我们就可以⽤该计算出的值更新对象中x属性的值,这就是属性动画的基本⼯作原理。属性动画中主要的类如下图所⽰:

下⾯会对上述类分别进⾏讲解。

Animator

属性动画主要的类都在android.animation命名空间下,Animator是属性动画的基类,其是⼀个抽象类,该类定义了许多重要的⽅法,如下所⽰:

setDuration(long duration)

通过setDuration⽅法可以设置动画总共的持续时间,以毫秒为单位。

start()

通过start⽅法可以启动动画,动画启动后不⼀定会⽴即运⾏。如果之前通过调⽤setStartDelay⽅法设置了动画延迟时间,那么

会在经过延迟时间之后再运⾏动画;如果没有设置过动画的延迟时间,那么动画在调⽤了start()⽅法之后会⽴即运⾏。在调⽤

了start()⽅法之后,动画的isStarted()⽅法就会返回true;在动画真正运⾏起来之后,动画的isRunning()⽅法就会返回true,这

时候动画才会调⽤TimeInterpolator才开始⼯作计算属性在某个时刻的值。调⽤动画的start()⽅法所在的线程必须绑定了⼀个

Looper对象,如果没有绑定就会报错。当然,UI线程(即主线程)早就默认绑定了⼀个Looper对象,所以在主线程中我们就

⽆需担⼼这个问题。如果我们想在⼀个View上使⽤属性动画,那么我们应该保证我们是在UI线程上调⽤的动画的start()⽅法。

start()⽅法运⾏后会触发动画监听器AnimatorListener的onAnimationStart⽅法的执⾏。

setStartDelay(long startDelay)

可以通过调⽤setStartDelay⽅法设置动画的延迟运⾏时间,⽐如调⽤setStartDelay(1000)意味着动画在执⾏了start()⽅法1秒之后才真正运⾏,这种情况下,在调⽤了start()⽅法0.5秒之后,isStarted()⽅法返回true,表⽰动画已经启动了,但是

isRunning()⽅法返回false,表⽰动画还未真正运⾏;在start()⽅法执⾏1秒之后,isStarted()⽅法还是返回true,isRunning()⽅

法也返回了true,表⽰动画已经真正开始运⾏了。通过调⽤getStartDelay()⽅法可以返回我们设置的动画延迟启动时间,默认

值是0。

setInterpolator(TimeInterpolator value)

我们可以通过调⽤setInterpolator⽅法改变动画所使⽤的时间插值器,由于视图动画也需要使⽤时间插值器,所以我们可以使

⽤android.view.animation命名空间下的⼀系列插值器,将其与属性动画⼀起⼯作。通过动画的getInterpolator⽅法可以获取我们设置的时间插值器。

setTarget(Object target)

可以通过调⽤动画的setTarget⽅法设置其要操作的对象,这样可以更新该对象的某个属性值。实际上,该⽅法对于

ValueAnimator作⽤不⼤,因为ValueAnimator不是直接与某个对象打交道的。setTarget⽅法对于ObjectAnimator作⽤较⼤,

因为ObjectAnimator需要绑定某个要操作的对象,下⾯会详细介绍。

pause()

Android中API Level 19在Animator中加⼊了pause()⽅法,该⽅法可以暂停动画的执⾏。调⽤pause()⽅法的线程必须与调⽤

start()⽅法的线程是同⼀个线程。如果动画还没有执⾏start()或者动画已经结束了,那么调⽤pause()⽅法没有任何影响,直接

被忽略。当执⾏了pause()⽅法后,动画的isPaused()⽅法会返回true。pause()⽅法运⾏后会触发动画监听器

AnimatorPauseListener的onAnimationPause⽅法的执⾏。

resume()

如果动画通过调⽤pause()⽅法暂停了,那么之后可以通过调⽤resume()⽅法让动画从上次暂停的地⽅继续运⾏。resume()⽅

法也是从API Level 19引⼊的,并且调⽤resume()⽅法的线程必须与调⽤start()⽅法的线程是同⼀个线程。如果动画没有处于

暂停状态(即isPaused()返回false),那么调⽤resume()⽅法会被忽略。resume()⽅法运⾏后会触发动画监听器

AnimatorPauseListener的onAnimationResume⽅法的执⾏。

end

end()⽅法执⾏后,动画会结束运⾏,直接从当前状态跳转到最终的完成状态,并将属性值分配成动画的终⽌值,并触发动画

监听器AnimatorListener的onAnimationEnd⽅法的执⾏。

cancel()

cancel()⽅法执⾏后,动画也会结束运⾏,但是与调⽤end⽅法不同的是,其不会将属性值分配给动画的终⽌值。⽐如⼀个动

画在400ms内将对象的x属性从0渐变为40,当运⾏到第200ms时调⽤了cancel()⽅法,那么属性x的最终值是20,⽽不是40,

这是与调⽤end()⽅法不同的,如果在第200ms调⽤了end()⽅法,那么属性x的最终值是40。调⽤cancel()⽅法后,会先触发

AnimatorListener的onAnimationCancel⽅法的执⾏,然后触发onAnimationEnd⽅法的执⾏。

clone()

Animator实现了java.lang.Cloneable接⼝。Animator的clone()⽅法会对动画进⾏拷贝,但是该⽅法默认实现的只是浅拷贝,⼦类可以重写该⽅法以实现深拷贝。

addListener (Animator.AnimatorListener listener)

可以通过addListener⽅法向Animator添加动画监听器,该⽅法接收的是AnimatorListener接⼝类型的参数,其具有四个⽅法:

onAnimationStart、onAnimationCancel、onAnimationEnd、onAnimationRepeat。我们上⾯已经介绍了前三个⽅

法,onAnimationRepeat⽅法会在动画在重复播放的时候被回调。Android中的AnimatorListenerAdapter类是个抽象类,其实

现了AnimatorListener接⼝,并为所有⽅法提供了⼀个空实现。

addPauseListener (Animator.AnimatorPauseListener listener)

可以通过addPauseListener⽅法可以向Animator添加动画暂停相关的监听器,该⽅法接收的是AnimatorPauseListener接⼝类

型的参数,具有两个⽅法:onAnimationPause和onAnimationResume,上⾯已经提到过,在此不再赘述。

AnimatorListenerAdapter同样也实现了AnimatorPauseListener接⼝,并为所有⽅法提供了⼀个空实现。

ValueAnimator

ValueAnimator继承⾃抽象类Animator。要让属性动画渐变式地更改对象中某个属性的值,可分两步操作:第⼀步,动画需要

计算出某⼀时刻属性值应该是多少;第⼆步,需要将计算出的属性值赋值给动画的属性。ValueAnimator只实现了第⼀步,也

就是说ValueAnimator只负责以动画的形式不断计算不同时刻的属性值,但需要我们开发者⾃⼰写代码将计算出的值通过对象

的setXXX等⽅法更新对象的属性值。ValueAnimator中有两个⽐较重要的属性,⼀个是TimeInterpolator类型的属性,另⼀个是TypeEvaluator类型的属性。

TimeInterpolator指的就是时间插值器,在上⾯我们已经介绍过,在此不再赘述。TypeEvaluator是什么呢?TypeEvaluator表

⽰的是ValueAnimator对哪种类型的值进⾏动画处理。ValueAnimator提供了四个静态⽅法ofFloat()、ofInt()、ofArgb()和

ofObject(),通过这四个⽅法可以对不同种类型的值进⾏动画处理,这四个⽅法对应了四种TypeEvaluator,下⾯会详细说明。

public static ValueAnimator ofFloat (float… values)

ofFloat⽅法接收⼀系列的float类型的值,其内部使⽤了FloatEvaluator。通过该⽅法ValueAnimator可以对float值进⾏动画渐

变,其使⽤⽅法如下所⽰:

ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 500f);

valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {