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應該不難理解屬性動畫了。