平方X翻译说明:
仅供参考,对正确性概不负责,翻译不对的欢迎指正,勿喷。
译于20160719,原文《ValueAnimator》
ValueAnimator
public class ValueAnimator
extends Animator
java.lang.Object
↳ android.animation.Animator
↳ android.animation.ValueAnimator
Known Direct Subclasses
ObjectAnimator, TimeAnimator
类概述
这个类提供一个简单的时间引擎来运行动画,它将计算动画的值并将值设置到对象上。
有一个简单的所有动画使用的动画脉冲,它运行在一个自定义(译注:custom)的handler中,以确保属性变化发生在UI线程中。
默认的,ValueAnimator通过使用AccelerateDecelerateInterpolator类来使用非线性的时间插值,这个插值器让动画展加速进入并且减速退出(译注1)。可以通过setInterpolator(TimeInterpolator)来设置插值器以改变这种行为。
译注1
这里说加速进入、减速退出,要注意的是AccelerateDecelerateInterpolator这个插值器是在开始和结束时慢,在中间加速。
//cos(π~2π)/2+0.5,函数是单调递增的,开始和结束慢
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
动画可以通动代画或资源文件创建,下面是用资源文件创建ValueAnimator的例子(译注2)
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType"
android:repeatCount="1"
android:repeatMode="reverse"/>
也可以通过 PropertyValuesHolder和Keyframe 这两种资源标签的组合,来创建多步动画。注意,你可以给每一个keyframe 都声明明确的分数(0到1),以这个分数来决定keyframe的值在在整个动画区间的何时到达。或者,你不写这个分数的话,所有的keyframes 将在整个区间平均分布。
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:repeatCount="1"
android:repeatMode="reverse">
<propertyValuesHolder>
<keyframe android:fraction="0" android:value="1"/>
<keyframe android:fraction=".2" android:value=".4"/>
<keyframe android:fraction="1" android:value="0"/>
</propertyValuesHolder>
</animator>
译注2:
这里说的不清楚,在
《Declaring Animations in XML》中有说明,在安卓3.1以上,应该把属性动画的xml文件放到res/animator/目录,我放到/anim下面有错误提示了。
上面这一个animator,放到目录下,用AnimatorInflater.loadAnimator加载,然后运行时,它会在0时为1,然后降到0.2时值为0.4,也就是说keyframe控制fraction时值为value。
开发指南
关于ValueAnimator的更多信息,看开发向导《Property Animation》
嵌套类
类型 | 介绍 |
---|---|
interface | ValueAnimator.AnimatorUpdateListener 实现这个接口可以将其添加为一个ValueAnimator实例的更新监听器,可以在当前帧的值计算出来时,收到回调 |
常量
类型 | 介绍 |
---|---|
int | INFINITE 值为:-1 (0xffffffff) 用于 setRepeatCount(int),表示无限地重复动画 |
int | RESTART 值为:1 (0x00000001) 当动画到结尾时,如果repeatCount(译注:重复次数)无限或者为正,动画会重头开始 |
int | REVERSE 值为:2 (0x00000002) 当动画到结尾时,如果repeatCount无限或者为正,动画会在每一次循环时反向 |
构造方法
ValueAnimator() 创建一个新的对象,默认的构造方法主要在内部调用,带参数的工厂方法更通用。 |
---|
公共方法
返回类型 | 介绍 |
---|---|
void | addUpdateListener(ValueAnimator.AnimatorUpdateListener listener) 给一组监听器中加上一个监听器,它们将在动画周期中收到更新事件回调 |
void | cancel() 取消动画 和end()不同,cancel()方法会让动画停在它的tracks(译注:轨迹)上。发送onAnimationCancel(Animator),再发送onAnimationEnd(Animator)。 这个方法必须在运行动画的线程中调用。 |
ValueAnimator | clone() 克隆(译注4) |
void | end() 结束动画。将动画设为动画属性的结尾值,然后调用监听器的onAnimationEnd(Animator)方法。 这个方法必须在运行动画的线程中调用。 |
float | getAnimatedFraction() 返回当前动画分数,它的值是是流逝的帧数除以总的帧数,被动画中最近的帧所使用。 |
Object | getAnimatedValue() 当只有一个属性在进行动画时,返回ValueAnimator计算的最新的值。只有在动画运行时,这个值才是合理的。这个只读属性的主要目的是在调用onAnimationUpdate(ValueAnimator)的时候返回值,这个方法在每一帧的值被计算出来时立即被调用。 返回值:只有一个属性在进行动画时,返回最近计算出的值。如果若干个属性在进行动画(通过若干个PropertyValuesHolder结构指定的属性),这个方法会返回这些对象中的每一个的值。 |
Object | getAnimatedValue(String propertyName) ValueAnimator计算的该属性的最近的值。这个只读属性的主要目的是在调用onAnimationUpdate(ValueAnimator)的时候返回值,这个方法在每一帧的值被计算出来时立即被调用。 |
long | getCurrentPlayTime() 获取当前动画位置所处时间,它等于当前时间减去开始时间。一个还没开始的动画会返回0,除非这个动画通过setCurrentPlayTime(long)或者setCurrentFraction(float)设置了时间,这时会返回所设置的值。 |
long | getDuration() 获取动画的长度,以毫秒记。默认是300毫秒。 |
staticlong | getFrameDelay() 帧与帧之前的时间间隔,以毫秒计。这是一个必要的动画尝试屡行的时间,但真实的间隔时间可能不同,这取决于系统系统负载和性能。这里一个静态的方法,因为相同的延时将被被应用到所有动画上,而这些动画运行在一个单一的时间循环内。(译注:翻译的不对,反正是public static)设个帧延时会在使用外部的定时资源来管理动画时被忽略,比如使用display refresh rate (vsync)。注意这个方法应该在调用start()方法的相同线程中被调用。如果线程没有Looper会返回运行错误。 |
TimeInterpolator | getInterpolator() 返回ValueAnimator使用的时间插值器。 |
int | getRepeatCount() 定义动画应该重复多少次,默认值是0。 返回值:重复次数或INFINITE |
int | getRepeatMode() 定义动画到达结尾时的操作。 返回值:REVERSE或者RESTART |
long | getStartDelay() 在调用start()后,延时多少时间开始启动画,以毫秒计。 |
long | getTotalDuration() 获取总的动画时间,包括动画系列、列始延时和重复。如果时间是无限的,返回DURATION_INFINITE |
PropertyValuesHolder[] | getValues() 返回动画运动的值范围。这些值储存在PropertyValuesHolder对象中,即使ValueAnimator是通过值数组创建的。 返回:一个PropertyValuesHolder对象的数组,它持有动画定义的数值、每一个属性。 |
boolean | isRunning() 返回是否在运行(已起启动并且过了开始动画间隔时间,并且还没结束。) |
boolean | isStarted() 返回动画是否已经开始且还没结束。对于可多次使用的动画器(大多数动画器都是,与createCircularReveal()产生的一次性动画器区别开),isStarted()是isRunning()的父集,因为一个startDelay不为0的动画器,在这个延时阶段,isStarted()返回true,但呆有在延时阶段完成后,isRunning()才返回true。不可重复的动画器在开始后总是返回true,因为它们无法到到一个未开始的状态。 |
static ValueAnimator | ofArgb(int… values) 构造并返回一个在颜色值间动画的ValueAnimator。单个值表示该值是动画的目标值,但一般是没用的,因为动画器没有办法确定动画的开始值(不同于ObjectAnimator,它可以通过动画的目标对象和属性来派生出开始值)。因此,一般应该用2个或更多的值。 |
static ValueAnimator | ofFloat(float… values) 构造并返回一个在浮点数值间动画的ValueAnimator。单个值同上。 |
static ValueAnimator | ofInt(int… values) 构造并返回一个在整型数值间动画的ValueAnimator。单个值同上。 |
static ValueAnimator | ofObject(TypeEvaluator evaluator, Object… values) 构造并返回一个在Object间动画的ValueAnimator。单个值同上。 注意:对象的值保存的是原始对象的引用,也就意味着这个方法调用后,动画器将影响原始值。如果对象在这个方法被调用后要外部改变值,那么调用者应该传一个对象的拷内。 因为ValueAnimator不知道在任意的对象中怎么动画,所以这个方法还需要一个TypeEvaluator对象来让动画器执行插值。 参数:TypeEvaluator evaluator,被每一帧动画调用以提供必要的对象与起始对象间的插值。 |
static ValueAnimator | ofPropertyValuesHolder(PropertyValuesHolder… values) 构造并返回一个动画的ValueAnimator,它的值在指明的Property ValuesHolder间。 |
void | pause() 暂停一个正在运行的动画。这个方法只应该在启动动画的同一线程中调用。如果一个动画还没有开始,或者已经结束,这个调用会被忽略。暂停动画后可以通过调用resume()来继续动画。 |
void | removeAllUpdateListeners() 移除所有监听动画更新的监听器。 |
void | removeUpdateListener(ValueAnimator.AnimatorUpdateListener listener) 从监听器组中移除一个。 |
void | resume() 继续一个暂停的动画,它会让动画从暂停时的点继续。这个方法只应该在启动动画的同一线程中调用。如果动画还没有暂停,调用这个方法会被忽略。 |
void | reverse() 反向播放动画。如果一个动画仍在运行,它将停止动画并从调用reverse()时动画已运行到点反向播放。如果动画没有在运行,它将从结束点反向播放。这个行为只适用于当前动画,未来播放的动画会使用默认的行为。 |
void | setCurrentFraction(float fraction) 设置当前动画的位置为指定的分数。这个分数应该在0到动画的总分数之间,包括任意的重复。也就是说,分数0将把动画定位到开头,1定位到结尾,如果是重复一次的动画,2将定位反向动画器的结尾(译注:这里翻译宝宝不明白,反向的2不是回到开头吗。)。如果一个动画还没有开始,设置这个分数后并不会向前移动到;它只会简单地设置值为这个分数,同时执行一些和这个值相关的操作。如果动画已经在运行,这个方法会设置当前分数值并且从那个点继续播放。改变分数值并不会调用Animator.AnimatorListener 的事件,这些事件只会在动画运行时处理。 参数:float fraction,设置动画前进至或后退至的值。不在0到最大分数间的值,将会被修正到正确的范围。 |
void | setCurrentPlayTime(long playTime) 设置当前动画的位置为指定的时间点。这个时间应该在0到动画的总时间之间,包括任意的重复。如果一个动画还没有开始,设置这个时间后并不会向前移动到;它只会简单地设置值为这个时间,同时执行一些和这个值相关的操作。如果动画已经在运行,这个方法会设置当前播放时间并且从那个点继续播放。 参数:long playTime,以毫秒记。 |
ValueAnimator | setDuration(long duration) 设置动画的长度。默认是300毫秒。这个值不能为负数。 |
void | setEvaluator(TypeEvaluator value) 当计算动画的值时所使用的evaluator。系统会根据构造函数中的起始值来自动分配一个浮点或整型的evaluator。如果构造函数的起始值不是基本类型,或者期望一个不同的evaluator(比如表示颜色的整理就需要),就可指定一个自定义的evaluator。比如,当用颜色值来进行动画时,就应该用一个ArgbEvaluator来获取正确的RGB插值。 如果ValueAnimator的动画范围值只有一组,这个evaluator会给那一组数值使用。如果有通过PropertyValuesHolder设置的多组数值在动画,这个evaluator只会指派给第一个PropertyValuesHolder使用。 |
void | setFloatValues(float… values) 设置浮点数值的动画区间。单个值表示该值是动画的目标值,但一般是没用的,因为动画器没有办法确定动画的开始值(不同于ObjectAnimator,它可以通过动画的目标对象和属性来派生出开始值)。因此,一般应该用2个或更多的值。 如果动画器中有通过PropertyValuesHolder设置的多组数值,这个方法只会设置第一个的数值。 |
staticvoid | setFrameDelay(long frameDelay) 每一帧动画间的间隔,以毫秒记。这是一个必要的动画尝试屡行的时间,但真实的间隔时间可能不同,这取决于系统系统负载和性能。这里一个静态的方法,因为相同的延时将被被应用到所有动画上,而这些动画运行在一个单一的时间循环内。(译注:翻译的不对,反正是public static)设个帧延时会在使用外部的定时资源来管理动画时被忽略,比如使用display refresh rate (vsync)。注意这个方法应该在调用start()方法的相同线程中被调用。如果线程没有Looper会返回运行错误。 |
void | setIntValues(int… values) 设置整型数值的动画区间。单个值和多组值同setFloatValues() |
void | setInterpolator(TimeInterpolator value) 计算动画经过的时间的时间插值器。这个插值器确定动画是线性还是非线性的动动。比如加速、减速,默认是AccelerateDecelerateInterpolator |
void | setObjectValues(Object… values) 设置动画的值区间。同ofObject |
void | setRepeatCount(int value) 设置动画重复次数。如果得复次数是0,动画将不重复。如果重复次数大于0或者是INFINITE,重复模式将被考虑在内。重复次数默认是0. |
void | setRepeatMode(int value) 定义动画在到达结尾时怎么操作。这个设置只有在重复次数大于0或者是INFINITE时才有用,默认是RESTART。 参数:int value,RESTART或者REVERSE |
void | setStartDelay(long startDelay) 在调用start()后延时多少时间开始动画,以毫秒记。注意这个开始延时应该总是非负的,一个负的开始延时将会被修改。(译注:原文是Any negative start delay will be clamped to 0 on N and above,不明白什么意思,在源码中也没有找到相关代码。) |
void | setValues(PropertyValuesHolder… values) 设置动画的每一个属性值。这个方法是使用一组值作为构造函数时被内部调用。但如果构造函数没有值,通过这个方法来设置值,是不能创建ValueAnimator的。 |
void | start() 开始动画。如果动画有非0的开始延时,在延时结束后动画会开始运行。非延时的动画将马上设置初始值,然后调用监听器的onAnimationStart(Animator) 通过这个方法开始运行的动画将在调用方法所在线程运行。这个线程要有一个Looper(否则会抛出运行异常)。同样的,如果一个动画改变视图层的对象属性,那么调用线程就应该是那个视图层的UI线程。 |
String | toString() 返回描述对象的字符串。通常toString方法返回一个“用文字描述”这个对象的字符串。返回结果应该简洁但信息丰富以便人阅读。推荐所有的子类都重写这个方法。 Object类的toString方法返回由Object的一个实例的类名,@符号,和该对象hashcode(一个无符号的十六进制表达式)组成的字符串。换句话说,这个方法的返回值等于 getClass().getName() + '@' + Integer.toHexString(hashCode()) |
译注4:clone()
创建并返回当前对象的copy(译注:拷贝),“copy”精确的含义决定于object类,通常的意思是,对于任意一个对象x,下列表达式的值为true
x.clone() != x
并且下面表达式的为true
x.clone().getClass() == x.getClass()
有一些不是绝对的要求,比如下面的表达式为true,但不是强制要求。
x.clone().equals(x)
按照约定,返回的对象应该通过super.clone()获得,如果一个类和它所有的父类(除了Object)都遵守这个约定,那么表达式成立x.clone().getClass() == x.getClass().
按照约定,这个方法返回的对象应该独立于当前对象(被克隆的)。为了实现这种独立性,通过super.clone()得到的对象必须修改一个或多个字段,再返回。一般地,复制一个包含内部“深层结构”的对象时,内部对象也要被复制并且被复制的对象引用。(译注:不会翻译,大概就是说如果clone的对象中有别的类型的字段,那个字段也要被克隆)如果一个类只包含基本类型的字段或不可变的字段,那么super.clone()返回的对象不需要修改任何字段。
Object类的clone方法执行特殊的克隆操作。首先如果一个类没有实现Cloneable接口,会抛出一个CloneNotSupportedException异常。注意,所的的数组都被视为实现了Cloneable接口,数组T[]的clone方法返回一个T[],T是任意的引用类型或基本类型。不同的,这个方法创建一个该对象的类的新实例,并且初始化所有的字段,初始字段的值和该对象的相应字段的值保持一致,as if by assignment(译注:不晓得啥意思);字段的内容不是他们自己克隆的。因些,这个对象的clone只是一个“浅克隆”操作,不是“深克隆”操作。
Object类没有实现Cloneable接口,所以克隆一个Object类将抛出错误。(译注:Object的clone方法是protected的)