如果你想实现一个安卓系统中没有的动画类型,你可以通过实现TypeEvaluator接口创建自己的计算实现。在Android系统已实现的类型有int(IntEvaluator),float(FloatEvaluator),或颜色(ArgbEvaluator)。
TypeEvaluator接口中只有一个evaluate()方法需要实现。这个方法会在动画的当前点返回对应的属性值。 下面是FloatEvaluator类的实现代码
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);
}
}
注意:当ValueAnimator(或ObjectAnimator)运行时,它会根据interpolator类计算当前运行部分的动画的数值(0和1之间),然后计算出具体是哪类插值。插值百分比就是TypeEvaluator接收的部分参数,所以当计算动画部分时,无需再考虑interpolator。
Interpolators定义了一个动画过程中的指定值的计算结果。例如,你可以指定在整个动画过程中线性发生动画,即动画在整个时间内均匀地移动,或者你可以指定在整个动画过程中发生非线性发生动画,比如,在动画的开头或结尾加速或减速。
在整个动画系统中Interpolators会得到已经执行的动画百分比。Interpolators会修改这个百分比以符合它所定义的动画类型。Android系统在android.view.animation包中提供一组通用的Interpolators实现。如果这些都不符合你的需要,你可以实现 TimeInterpolator接口来创建一个。
下面两个例子展示了AccelerateDecelerateInterpolator 和LinearInterpolator 是如何计算这个百分比数值的。
AccelerateDecelerateInterpolator
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
LinearInterpolator
public float getInterpolation(float input) {
return input;
}
下表是根据这些计算得来的在1000毫秒内的数据:
经过时间(ms) | 线性(LinearInterpolator) | 非线性(AccelerateDecelerateInterpolator) |
---|---|---|
0 | 0 | 0 |
200 | .2 | .1 |
400 | .4 | .345 |
600 | .6 | .8 |
800 | .8 | .9 |
1000 | 1 | 1 |
如表所示,该LinearInterpolator变化值,以相同的速度,200ms经过0.2。AccelerateDecelerateInterpolator同前面相比在200ms到600ms之间速度较快、600ms到1000ms之间速度较慢。
一个关键帧的对象由时间/值对组成,你可以在一个动画的具体时间定义一个特定的状态。每个关键帧也可以有自己的Interpolators控制在一上个关键帧和当前关键帧时间的动画行为。
为了实例化一个关键帧的对象,你必须使用ofint(),offloat() ofobject()这三个工厂方法之一,来对应关键帧的类型。然后调用ofkeyframe()工厂方法来获得一个PropertyValuesHolder对象。一旦你有了以上两个对象,你就可以使用它们来实现一个动画效果。示例代码如下所示
Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation)
rotationAnim.setDuration(5000ms);
属性动画系统在对view添加的动画是流畅的。视图动画系统转化的视图对象的改变仅仅是基于视图的绘制。因为视图本身没有绘制的功能,这种绘制由每个视图的容器来处理。这导致在视图动起来的同时,视图对象本身没有变化。即使绘制的位置已经同原来位置有所不同。在Android 3.0以后,可以使用属性动画和添加对应的setter和getter方法来解决这个问题。
属性动画系统可以将屏幕上的视图通过改变该对象的实际属性使之动起来。此外,当View对象的属性发生改变时,它也会自动调用invalidate()方法刷新屏幕。新特性下视图中的支持动画的属性有:
translationX and translationY: 这些属性控制位于自身容器中以左上角为顶点的坐标
rotation, rotationX, and rotationY: 这些属性控制二维旋转(平面)和三维旋转
scaleX and scaleY: 这些属性控制二维基于枢轴点的视图缩放
pivotX and pivotY: 这些属性控制的枢轴点的位置,适用于旋转和缩放。默认情况下,枢轴点位于对象的中心
x and y: 这些用来简单有效的描述位于其容器视图的最终位置,分别为left和translationX的和值以及top和translationY的和值
alpha: 视图透明度,这个值为1(默认值)时:不透明,为0时,不可见(全透明)
想针对View的某个属性添加动画,比如如颜色或rotation,你只需要创建一个属性动画来指定视图的属性,例如:
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
ViewPropertyAnimator的提供了一个简单的方法来同时对一个对象的一些属性进行修改。它的所做的就像一个ObjectAnimator,因为它修改View的属性的实际值,但当同时修改多个属性时会更有效。此外,使用ViewPropertyAnimator代码更简洁也更容易阅读。下面的代码片段展示了在使用多个ObjectAnimator对象的不同,一个ObjectAnimator对象,以及ViewPropertyAnimator对视图的x、y属性进行修改时候的区别
多个ObjectAnimator
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(animX, animY);
animSetXY.start();
一个ObjectAnimator
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();
ViewPropertyAnimator
myView.animate().x(50f).y(100f);
属性动画系统允许通过XML定义动画来替代编码。通过在XML中定义你的动画,你可以很容易地在多个页面和动画队列中重用你的动画。
区分使新的属性动画同原有的动画文件有所区别,从Android 3.1开始,你应该保存XML文件在res/animator/ 目录下(而不是res/anim/)。animator的名称是可选的,但首先你得在Eclipse的ADT插件使用layout editor tools (ADT 11.0.0 +版本),因为ADT只搜索res/animator/目录下的属性动画资源。
下面是属性动画类XML支持的XML标签:
ValueAnimator - < animator >
ObjectAnimator - < objectAnimator >
AnimatorSet - < set >
下面的例子是一个序列中的两组动画,两组动画同时执行:
<set android:ordering="sequentially">
<set>
<objectAnimator
android:propertyName="x"
android:duration="500"
android:valueTo="400"
android:valueType="intType"/>
<objectAnimator
android:propertyName="y"
android:duration="500"
android:valueTo="300"
android:valueType="intType"/>
</set>
<objectAnimator
android:propertyName="alpha"
android:duration="500"
android:valueTo="1f"/>
</set>
为了运行这个动画,你必须使用AnimatorInflater对象来得到一个XML动画,然后所有动画开始指定动画对象。调用 setTarget()即可为该XML下的所有动画指定同一个目标。下面的代码展示了如何实现:
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
R.anim.property_animator);
set.setTarget(myObject);
set.start();
Property Animation Part III(属性动画 第三部分)
原文地址:http://blog.csdn.net/duanymin/article/details/44410291