Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 屬性動畫之ObjectAnimator

屬性動畫之ObjectAnimator

編輯:關於Android編程

ObjectAnimator,通過設置改變對象的屬性來實現動畫效果,常用的方法有這麼幾種,ofFloat()、ofInt()、ofObject()、ofArgb()、ofPropertyValuesHolder(),具體含義及使用我們在下面的實例中進行講解。

一、動畫類型

使用ObjectAnimator也是可以輕松的實現平移、縮放、旋轉、透明度這幾種動畫效果的,與補間動畫的使用效果是一樣的,那就先來看看這幾種常用的動畫是怎麼實現的。

工程代碼裡就是一個ImageView控件和Activity,






@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_object_animator);   
        head = (ImageView) findViewById(R.id.head);
    }

我們這裡就是對ImageView控件head實現動畫效果,本質就是改變head的屬性。

1.平移(translate)

// 平移 private void translateAnimation() { ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "translationX", 0.0f, 350.0f, 0.0f); objectAnimator.setDuration(2000); objectAnimator.setRepeatCount(Animation.INFINITE); objectAnimator.setRepeatMode(Animation.RESTART); objectAnimator.start(); }
\ 這段代碼就是用來實現控件的平移,我們來逐行分析這段代碼。

 

ofFloat方法的函數原型,

public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)

參數含義:

target:動畫操作的對象,我們這裡的操作對象就是ImageView控件head

 

propertyName:屬性名稱,這裡的"translationX"屬性值意思就是在水平方向移動,如果是"translationY"就是在垂直方向移動,下面講到的其動畫效果也是這個意思,這個屬性值跟我們在xml文件中設置屬性值得名稱是一致的,比如

"android:translationY"。

values:動畫過渡值,過渡值可以有一個到N個,如果是一個值的話,就默認是這個動畫過渡值的結束值,如果有N個值,動畫就在這N個值之間過渡,如本例中有三個過渡值"0.0f, 350.0f, 0f",意思就是從當前位置向右滑到350的位置,再滑到位置0,即初始位置。

然後是動畫的設置,

    objectAnimator.setDuration(2000);//動畫的時間間隔
    objectAnimator.setRepeatCount(Animation.INFINITE);//重復次數
    objectAnimator.setRepeatMode(Animation.RESTART);//重復模式

最後start,動畫就開始執行了

     objectAnimator.start();

2.縮放(scale)

// 縮放
private void scaleXAnimation() {
    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "scaleX", 1.0f, 1.5f);
    objectAnimator.setDuration(2000);
    objectAnimator.setRepeatCount(Animation.INFINITE);
    objectAnimator.setRepeatMode(Animation.RESTART);
    objectAnimator.start();
}
\
3.旋轉(rotate)
// 旋轉
private void rotateAnimation() {
    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "rotationX", 0.0f, 90.0f,0.0F);
    objectAnimator.setDuration(2000);
    objectAnimator.setRepeatCount(Animation.INFINITE);
    objectAnimator.setRepeatMode(Animation.RESTART);
    objectAnimator.start();
}
\
4.透明度(alpha)
// 透明度
private void alphaAnimation() {
    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "alpha", 1.0f, 0.3f, 1.0F);
    objectAnimator.setDuration(2000);
    objectAnimator.setRepeatCount(Animation.INFINITE);
    objectAnimator.setRepeatMode(Animation.RESTART);
    objectAnimator.start();
}
\

 

可能我們也注意到了,在縮放效果的實例中,圖片被放大後就保持當前的狀態,沒有變為初始的樣子,這是因為我們在設置過渡值是最終的狀態是1.5f,就放大到1.5倍,並沒有讓它回到原來的狀態,從這點就可以看出,屬性動畫是真真切切的可以改變控件的屬性的,這是與補間動畫的最大不同,補間動畫在動畫結束後都將回到初始狀態。所以說,屬性動畫的使用就顯得更加的靈活。至於上面的其他三個實例,最終回到初始狀態,是因為我們在設過渡值的時候最終狀態設定的就是初始狀態。

剛才我們討論了幾種常見的動畫效果,如果僅有這些功能的話,那就與補間動畫沒有太大的區別。其實,屬性動畫還可以設置其他的屬性值。ObjectAnimator的ofObject方法,就是用來對任意對象進行動畫設置的,如字體顏色,直接看實例

 

int startColor = 0xffff0000;
int endColor = 0xff00ff00;
ObjectAnimator objectAnimator4 = ObjectAnimator.ofObject(txt, "textColor", new TypeEvaluator() {
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
int startInt = (Integer) startValue;
int startA = (startInt >> 24) & 0xff;
int startR = (startInt >> 16) & 0xff;
int startG = (startInt >> 8) & 0xff;
int startB = startInt & 0xff;

int endInt = (Integer) endValue;
int endA = (endInt >> 24) & 0xff;
int endR = (endInt >> 16) & 0xff;
int endG = (endInt >> 8) & 0xff;
int endB = endInt & 0xff;

return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
                (int)((startR + (int)(fraction * (endR - startR))) << 16) |
                (int)((startG + (int)(fraction * (endG - startG))) << 8) |
                (int)((startB + (int)(fraction * (endB - startB))));
    }
}, startColor, endColor);
objectAnimator4.setDuration(3000);
objectAnimator4.start();
\

 

ofObject方法的原型

public static ObjectAnimator ofObject(Object target, String propertyName, TypeEvaluator evaluator, Object... values)
我們看到它比ofFloat多了一個TypeEvaluator參數,它是用來告知系統如何進行屬性值過渡的,由於ofObject是任意屬性,所以需要自己實現TypeEvaluator,ofFloat沒有該參數是因為系統默認實現了其過渡行為FloatEvaluator,關於TypeEvaluator我們會單獨講解,這邊就不在詳述了。 除了字體顏色外,還可以設置背景色"backgroundColor"等。 剛才的字體顏色除了使用ofObject方法外,還可以使用ofArgb,但需要SDK版本21上支持,目前市面上很多機型還是21以下的,暫時我們最好不要使用。
ObjectAnimator objectAnimator2 = ObjectAnimator.ofArgb(txt, "textColor", 0x000, 0x00FF00);
objectAnimator2.start();

二、常用設置 在上面的例子中,我們已經對動畫進行了一些設置,如間隔、重復次數等等,下面就將常見的設置羅列出來。

1.setInterpolator():設置動畫插值

控制動畫的變化速率,系統中定義了好幾種Interpolator:

LinearInterpolator--均勻的速率改變

AccelerateDecelerateInterpolator--先加速後減速

AccelerateInterpolator--加速

DecelerateInterpolator--減速

CycleInterpolator--動畫循環播放特定的次數,速率改變沿著正弦曲線 2.setDuration():設置動畫執行時間,動畫時間以毫秒為單位(ms)

3.setRepeatCount():設置動畫重復次數

大於0的值就代表重復幾次,如果需要無限循環,設為-1,上面的Animation.INFINITE是系統給的常量,值為-1,代表無限循環,我們建議使用這個常量,如果設為0呢?也是執行一次。

4.setRepeatMode():設置動畫重復模式

5.setStartDelay():設置動畫延時操作,也是以毫秒為單位(ms)

6.setTarget():設置動畫的對象

操作對象,上面的例子中將動畫對象通過ofXXX方傳遞,如果需要改變動畫對象,但動畫效果不變,我們可以使用該方法來設置。

objectAnimator.setTarget(txt);//將動畫對象head變為txt
7.setEvaluator():設置動畫過度的評估者,即設置TypeEvaluator對象,後面會詳細介紹   三、組合動畫 上面講到的都是單一的動畫,在實際使用時,有可能同時需要多種動畫效果,比如同時在水平方向和垂直方向進行縮放並且同時繞水平方向旋轉,要實現這樣的效果就必須用到組合動畫。可以有三種方式來實現,一一講解。 1.AnimatorSet AnimatorSet可以讓幾個動畫同時執行,也可以設置執行順序、延遲執行等,
    after(Animator anim)--將現有動畫插入到傳入的動畫之後執行
    after(long delay)--將現有動畫延遲指定毫秒後執行
    before(Animator anim)--將現有動畫插入到傳入的動畫之前執行
    with(Animator anim)--將現有動畫和傳入的動畫同時執行

playSequentially(Animator... items)--依次執行
private void multiAnimation() {
        ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(head, "scaleX", 1.0f, 2.5f, 1.0f);
        ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(head, "scaleY", 1.0f, 2.5f, 1.0f);
        ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(head, "rotationX", 0.0f, 90.0f,0.0F);
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.play(objectAnimator1).with(objectAnimator2).with(objectAnimator3);
        animatorSet.setDuration(2000);
        animatorSet.start();
    }
\

 

讓動畫同時執行除了使用with方法外,還可以用playTogether方法,

 

animatorSet.playTogether(objectAnimator1, objectAnimator2, objectAnimator3);
其他幾種就不在演示了。 2.PropertyValuesHolder
    這種方式只能多個動畫一起執行,不同設置先後順序。
private void multiAnimation2() {
        PropertyValuesHolder valuesHolder = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 2.5f, 1.0f);
        PropertyValuesHolder valuesHolder1 = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 2.5f, 1.0f);
        PropertyValuesHolder valuesHolder2 = PropertyValuesHolder.ofFloat("rotationX", 0.0f, 90.0f,0.0F);
        ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(head, valuesHolder, valuesHolder1, valuesHolder2);
        objectAnimator.setDuration(2000);
        objectAnimator.start();
}
3.ViewPropertyAnimator 該類是多屬性動畫,從名字就可以看出該類的作用對象是view,當一個view對象需要同時執行多個屬性動畫的時候就可以考慮使用該類了。比如說:一個ImageView先右移動的同時進行放大一倍的動畫效果實現如下
private void viewPropertyAnimator() {
        ViewPropertyAnimator animator = head.animate();
        animator.translationX(200)
                .scaleX(2)
                .scaleY(2)
                .setDuration(2000)
                .start();
    }

四、動畫的監聽

一般情況下,我們除了需要動畫效果外,還需要對動畫的執行過程進行監聽,在執行前、執行結束後或者執行過程中,做出相應的處理,比如動畫結束後,請求網絡數據。系統給我們提供幾種監聽接口,來監聽動畫的各個狀態,如AnimatorListener,

private void animationListener() {
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "translationX", 0.0f, 350.0f, 0f);
        objectAnimator.setDuration(2000);
        objectAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                Log.d("dingfeng", "onAnimationStart......");
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                Log.d("dingfeng", "onAnimationEnd......");
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                Log.d("dingfeng", "onAnimationCancel......");
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                Log.d("dingfeng", "onAnimationRepeat......");
            }
        });
        objectAnimator.start();
    }

可以根據不同需求來實現接口裡面的四個方法,可以根據需要做相應的處理。但有時候你會覺得我不需要監聽動畫的四種狀態,我只需要監聽動畫結束時候的狀態,使用上面的方法就會感覺代碼臃腫了,不過沒關系,Android系統給我們提供了一個更好用的方法,

private void animationListener2() {
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "translationX", 0.0f, 350.0f, 0f);
        objectAnimator.setDuration(2000);
        objectAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                Log.d("dingfeng", "onAnimationEnd......");
            }
        });
        objectAnimator.start();
    }
    可以看出,我們使用了AnimatorListenerAdapter動畫接口適配器代替AnimatorListener接口。其實AnimatorListenerAdapter的源碼只是一個實現了AnimatorListener接口的抽象類而已,
    你需要監聽哪種動畫狀態就重寫哪種方法就可以了。
    除此之外,AnimatorUpdateListener接口就可以讀取到動畫的每個更新值。

private void animationListener3() { ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "translationX", 0.0f, 350.0f, 0f); objectAnimator.setDuration(2000); objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float)animation.getAnimatedValue(); Log.d("dingfeng", "onAnimationUpdate......"+value); } }); objectAnimator.start(); }
一般情況下不太用到這個接口,但是在自定義動畫的時候,通過該接口,可以實現很多復雜的效果。 五、xml編寫動畫 當然,我們也可以在xml文件中配置動畫,這樣做可以比較好的復用這些動畫,減少代碼量。 1.在資源目錄下創建animator文件夾 將編寫的xml文件放在該目錄下,如下圖 \

我們創建兩個動畫文件,一個是旋轉動畫,一個組合動畫

 





2.加載動畫 使用AnimatorInflater加載動畫文件
head = (ImageView) findViewById(R.id.head);
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.multi);
animator.setTarget(head);
animator.start();
這樣就OK了,還是很容易的。  
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved