Android-属性动画原理总结
Android属性动画允许开发者随着时间的流逝改变对象的属性。
我们用一个小案例看下它是如何工作的。
下面是官方文档提供的一张原理图:
从图中可以看到ValueAnimator类封装了:
一个TimeInerpolator,
一个TypeEvaluator,
动画执行的时间duration,
属性的起始值startPropertyValue,属性终止值endPropertyValue。
当我们使用属性动画就需要提供这些信息,可以是系统提供的,我们也可以自己实现,那么当一个ValueAnimator设置了这些属性,它门是如何协同工作的呢?
(勿喷。。。)
首先系统根据已经流失的时间和持续时间计算出一个elapsed fraction,将它传递给时间插值器的getInterpolation(float input)方法,该方法对输入值进行映射到0-1之间的interpolated fraction,接着该值被传递给Evaluator的evaluate(float fraction, Point start, Point end)方法,又该方法返回本次计算的属性值,可以在AnimatorUpdateListener的onAnimationUpdate(ValueAnimator anition)方法的参数animation的getAnimatedValue()方法获得最新的属性,然后重新给对象设置该属性,完成对对象属性的修改。
下面举个栗子:该例子演示了一个红色的小球匀速运动的例子。
MainActivity.java
1 public class MainActivity extends Activity { 2 3 4 private ImageView ivBall; 5 6 @Override 7 protected void onCreate(Bundle savedInstanceState) { 8 super.onCreate(savedInstanceState); 9 setContentView(R.layout.ball); 10 11 ivBall = (ImageView) findViewById(R.id.ivBall); 12 } 13 14 /** 15 * 对应Button的点击事件 16 * @param view 17 */ 18 public void run(View view) 19 { 20 //设置自定义的TypeEvaluator,起始属性,终止属性 21 ValueAnimator valueAnimator = ValueAnimator.ofObject(new MyTypeEvaluator(), new Point(0, 0), new Point(0, 0)); 22 //设置持续时间 23 valueAnimator.setDuration(2000); 24 //设置加速时间插值器 25 valueAnimator.setInterpolator(new MyInperpolator()); 26 valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { //设置监听器 27 @Override 28 public void onAnimationUpdate(ValueAnimator animation) { 29 //将最新计算出的属性值设置给ImageView 30 Point point = (Point) animation.getAnimatedValue(); 31 ivBall.setX(point.x); 32 ivBall.setY(point.y); 33 } 34 }); 35 36 //开启动画 37 valueAnimator.start(); 38 } 39 40 /** 41 * 自定义时间插值器,这里实现了线性时间插值器 42 */ 43 class MyInperpolator implements TimeInterpolator 44 { 45 46 @Override 47 public float getInterpolation(float input) { 48 return input; 49 } 50 } 51 52 /** 53 * 实现的自己的TypeEvaluator 54 */ 55 class MyTypeEvaluator implements TypeEvaluator<Point> { 56 57 @Override 58 public Point evaluate(float fraction, Point startValue, Point endValue) { 59 Point point = new Point(); 60 point.x = startValue.x + fraction * 500; 61 point.y = startValue.y + fraction * 500; 62 63 return point; 64 } 65 } 66 67 68 /** 69 * 保存坐标信息 70 */ 71 class Point 72 { 73 float x; 74 float y; 75 public Point() 76 {} 77 78 public Point(float x, float y) { 79 this.x = x; 80 this.y = y; 81 } 82 } 83 84 }
布局文件:
ball.xml:
1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:orientation="vertical" android:layout_width="match_parent" 4 android:layout_height="match_parent"> 5 6 <ImageView 7 android:id="@+id/ivBall" 8 android:layout_width="40dp" 9 android:layout_height="40dp" 10 android:background="@drawable/blue_ball"/> 11 12 <LinearLayout 13 android:layout_width="wrap_content" 14 android:layout_height="wrap_content" 15 android:layout_alignParentBottom="true"> 16 17 <Button 18 android:id="@+id/btnVertical" 19 android:layout_width="wrap_content" 20 android:layout_height="wrap_content" 21 android:text="run" 22 android:onClick="run"/> 23 24 </LinearLayout> 25 26 27 </RelativeLayout>
小球的背景:
blue_ball.xml:
1 <?xml version="1.0" encoding="utf-8"?> 2 <shape xmlns:android="http://schemas.android.com/apk/res/android" 3 android:shape="oval"> 4 5 6 <solid android:color="#0000ff"></solid> 7 <size 8 android:width="40dp" 9 android:height="40dp"></size> 10 <gradient 11 android:startColor="#FFFF0000" 12 android:endColor="#80FF00FF" 13 android:angle="45"/> 14 <padding android:left="7dp" 15 android:top="7dp" 16 android:right="7dp" 17 android:bottom="7dp" /> 18 <corners android:radius="8dp" /> 19 20 </shape>
最终的效果是:
通过这个例子再结合官方文档http://developer.android.com/guide/topics/graphics/prop-animation.html#interpolators应该不难理解属性动画了。