Android 屬性動畫Property Animation(下)

_小馬快跑_發表於2017-12-15
  1. Android 屬性動畫Property Animation(上)
  2. Android 屬性動畫Property Animation(中)

本篇來介紹一下屬性動畫中另一個重要的類ObjectAnimator~

  • ObjectAnimator ObjectAnimator是 ValueAnimator的子類,它是可以直接對任意物件的任意屬性進行動畫操作的,因為ValueAnimator是父類,所以ValueAnimator中可以使用的方法在ObjectAnimator中也是可以使用的,ObjectAnimator可以用XML表示,建立object_anim.xml如下:
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:valueTo="200"
    android:valueType="floatType"
    android:propertyName="y"
    android:repeatCount="1"
    android:repeatMode="reverse"/>
複製程式碼

程式碼中呼叫XML檔案:

ObjectAnimator objectAnimator = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.object_anim);
objectAnimator.setTarget(myObject);
objectAnimator.start();
複製程式碼

如果想建立更復雜一些的動畫,需要用到PropertyValuesHolder來對各個屬性分別做動畫,如:

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
                android:duration="1000"
                android:repeatCount="1"
                android:repeatMode="reverse">
    <propertyValuesHolder android:propertyName="x" android:valueTo="400"/>
    <propertyValuesHolder android:propertyName="y" android:valueTo="200"/>
</objectAnimator>
複製程式碼

如果想更復雜一些,還要用到keyframe (關鍵幀),fraction是當前進度,取值範圍(0,1),插值器interpolator 是可選的,預設是 AccelerateDecelerateInterpolator,示例:

<propertyValuesHolder android:propertyName="x" >
    <keyframe android:fraction="0" android:value="800" />
    <keyframe android:fraction=".2"
              android:interpolator="@android:anim/accelerate_interpolator"
              android:value="1000" />
    <keyframe android:fraction="1"
              android:interpolator="@android:anim/accelerate_interpolator"
              android:value="400" />
</propertyValuesHolder>
<propertyValuesHolder android:propertyName="y" >
    <keyframe/>
    <keyframe android:fraction=".2"
              android:interpolator="@android:anim/accelerate_interpolator"
              android:value="300"/>
    <keyframe android:interpolator="@android:anim/accelerate_interpolator"
              android:value="1000" />
</propertyValuesHolder>
複製程式碼

程式碼中使用ObjectAnimator:

//ofFloat(Object target, String propertyName, float... values) 
//第一個引數為object型別的target,這裡是textview
//第二個引數是要做動畫的屬性值
//最後一個可以傳入任意個數的引數,動畫在他們數值之間過渡
 ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tv_text, "rotation", 0f, 20f, -20f, 20f, -20f, 0f);
 //動畫時長
  objectAnimator.setDuration(3000);
  //動畫重複次數
  objectAnimator.setRepeatCount(2);
  //動畫重複模式
  objectAnimator.setRepeatMode(ValueAnimator.RESTART);
  //設定動畫插值器
  objectAnimator.setInterpolator(new AccelerateInterpolator());
  //設定監聽器
  objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                Log.e("TTT", "value is " + value);
            }
        });
  //啟動動畫
  objectAnimator.start();
複製程式碼

ofFloat()中第二個引數傳入屬性值的是"rotation",那麼這個引數都可以用哪些值呢?答案是任何值!因為ObjectAnimator針對於任意物件的,它的工作就是不斷地向某個物件中的某個屬性進行賦值,然後物件根據屬性值的改變再來決定如何展現出來。系統不會根據這個屬性值名稱去查詢,而是會查詢對應的get和set方法。

上面程式碼效果圖:

object_animator.gif

上面使用的是ObjectAnimator.ofFloat()來建立浮點數值的ObjectAnimator例項,那麼如果想建立自定義object的ObjectAnimator例項呢?這時就要用ObjectAnimator.ofObject()來建立了,如:

ObjectAnimator ofObject(Object target, String propertyName,TypeEvaluator evaluator, Object... values)
複製程式碼

這裡要用到自定義Evaluator 了,Android 屬性動畫Property Animation(上) 中已經介紹過,Evaluator通過給定的動畫起始值(startValue)和結束值(endValue)以及動畫當前進度(fraction)來計算當前動畫的進度值。先來看下幾個常用的Evaluator, IntEvaluator:

public class IntEvaluator implements TypeEvaluator<Integer> {
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        int startInt = startValue;
        return (int)(startInt + fraction * (endValue - startInt));
    }
}
複製程式碼

FloatEvaluator:

public class FloatEvaluator implements TypeEvaluator<Number> {
    public Float evaluate(float fraction, Number startValue, Number endValue) {
        float startFloat = startValue.floatValue();
        return startFloat + fraction * (endValue.floatValue() - startFloat);
    }
}
複製程式碼

**返回的當前進度值=起始值+(結束值-起始值) x 當前進度,**ArgbEvaluator也是一樣道理。如果用ofInt()來定義動畫,動畫中的進度值應該都是整形的,如果用ofFloat()來定義動畫,那麼動畫中的值也都是浮點型的。以ofFloat(0.0f,1.0f)為例:起始值為0.0f,結束值是1.0f,假如當前進度(fraction)為50%,則當前進度值=0.0f+(1.0f-0.0f)x 0.5=0.5,在AnimatorUpdateListener監聽器中通過animation.getAnimatedValue()函式拿到Evaluator中返回的值,如果需要自定義Evaluator,則需要實現TypeEvaluator介面:

 public class MyEvalutor implements TypeEvaluator {
        @Override
        public Object evaluate(float fraction, Object startValue, Object endValue) {
            return null;
        }
    }
複製程式碼

下面建立一個自定義object的ObjectAnimator例子,先定義一個ObInfo類:

 public class ObInfo implements Serializable {
     public int color;//用來定義顏色
     public float x; //用來定義X軸
     public float y; //用來定義Y軸

     public ObInfo(int color, float x, float y) {
         this.color = color;
         this.x = x;
         this.y = y;
        }
    }
複製程式碼

接著自定義TypeEvaluator :

 public class MyEvalutor implements TypeEvaluator<ObInfo> {

   @Override
   public ObInfo evaluate(float fraction, ObInfo startValue, ObInfo endValue) {
       float x = startValue.x + fraction * (endValue.x - startValue.x);
       float y = startValue.y + fraction * (endValue.y - startValue.y);
       int color = (int) (startValue.color + fraction * (endValue.color - startValue.color));
       return new ObInfo(color, x, y);
        }
    }
複製程式碼

最後實現動畫:

ObInfo info1 = new ObInfo(0xffffff00, 500, 200);
ObInfo info2 = new ObInfo(0xff0000ff, 500, 1000);
ValueAnimator animator = ValueAnimator.ofObject(new MyEvalutor(), info1, info2, info1);
animator.setDuration(4000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        ObInfo info = (ObInfo) animation.getAnimatedValue();
        tv_text.layout(tv_text.getLeft(), (int) info.y, tv_text.getRight(), (int) (info.y + tv_text.getHeight()));
        tv_text.setTextColor(info.color);
    }
  });
animator.start();
複製程式碼

文字先往下移動,再返回原處,移動過程中顏色也不斷變化,效果圖:

evalutor.gif

如果想監聽動畫過程只需新增監聽器:

    objectAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
              //動畫開始前呼叫
            }

            @Override
            public void onAnimationEnd(Animator animation) {
              //動畫結束時呼叫
            }

            @Override
            public void onAnimationCancel(Animator animation) {
              //動畫取消時呼叫
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
              //動畫重複執行時呼叫
            }
        });
複製程式碼

如果只想用其中的一個,只需改成介面卡類AnimatorListenerAdapter即可:

 objectAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationCancel(Animator animation) {
                super.onAnimationCancel(animation);
            }
        });
複製程式碼
常用方法 備註
ofFloat、ofInt、ofArgb、ofObject、ofPropertyValuesHolder ofFloat(),ofInt(),ofArgb(),ofObject(),ofPropertyValuesHolder()分別是用來建立浮點型、整形、顏色值、自定義object、包含PropertyValuesHolder的animator例項

相關文章