自己定義控件三部曲之動畫篇(七)——ObjectAnimator基本使用


前言:
假如生活欺騙了你,
不要悲傷,不要心急!


憂郁的日子里須要鎮靜:
相信吧,快樂的日子終將會來臨!


心兒永遠向往着未來;
如今卻常是憂郁。
一切都是瞬息,一切都將會過去;
而那過去了的,就會成為親切的懷戀。


—–普希金

相關文章:

《Android自己定義控件三部曲文章索引》http://blog.csdn.net/harvic880925/article/details/50995268

一、概述

1、引入

上幾篇給大家講了ValueAnimator。但ValueAnimator有個缺點。就是僅僅能對數值對動畫計算。我們要想對哪個控件操作。須要監聽動畫過程,在監聽中對控件操作。這樣使用起來相比補間動畫而言就相對照較麻煩。


為了能讓動畫直接與相應控件相關聯,以使我們從監聽動畫過程中解放出來,谷歌的開發者在ValueAnimator的基礎上,又派生了一個類ObjectAnimator;
因為ObjectAnimator是派生自ValueAnimator的。所以ValueAnimator中所能使用的方法,在ObjectAnimator中都能夠正常使用。


但ObjectAnimator也重寫了幾個方法,比方ofInt(),ofFloat()等。我們先看看利用ObjectAnimator重寫的ofFloat方法怎樣實現一個動畫:(改變透明度)

ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"alpha",1,0,1);
animator.setDuration(2000);
animator.start();
效果圖例如以下:

我們這里還是直接使用上一篇的框架代碼;(當點擊start anim時運行動畫)從上面的代碼中能夠看到構造ObjectAnimator的方法非常簡單:

public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) 
  • 第一個參數用於指定這個動畫要操作的是哪個控件
  • 第二個參數用於指定這個動畫要操作這個控件的哪個屬性
  • 第三個參數是可變長參數。這個就跟ValueAnimator中的可變長參數的意義一樣了。就是指這個屬性值是從哪變到哪。像我們上面的代碼中指定的就是將textview的alpha屬性從0變到1再變到0;
以下我們再來看一下怎樣實現旋轉效果:
ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,180,0);
animator.setDuration(2000);
animator.start();
效果圖例如以下:

從代碼中能夠看到,我們僅僅須要改變ofFloat()的第二個參數的值就能夠實現相應的動畫;
那么問題來了,我們怎么知道第二個參數的值是啥呢?

2、setter函數

我們再回來看構造改變rotation值的ObjectAnimator的方法

ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,180,0);
TextView控件有rotation這個屬性嗎?沒有,不光TextView沒有,連它的父類View中也沒有這個屬性。那它是怎么來改變這個值的呢?事實上,ObjectAnimator做動畫,並非依據控件xml中的屬性來改變的,而是通過指定屬性所相應的set方法來改變的。比方,我們上面指定的改變rotation的屬性值。ObjectAnimator在做動畫時就會到指定控件(TextView)中去找相應的setRotation()方法來改變控件中相應的值。相同的道理,當我們在最開始的演示樣例代碼中,指定改變”alpha”屬性值的時候,ObjectAnimator也會到TextView中去找相應的setAlpha()方法。那TextView中都有這些方法嗎,有的。這些方法都是從View中繼承過來的,在View中有關動畫。總共同擁有以下幾組set方法:
//1、透明度:alpha
public void setAlpha(float alpha)

//2、旋轉度數:rotation、rotationX、rotationY
public void setRotation(float rotation)
public void setRotationX(float rotationX)
public void setRotationY(float rotationY)

//3、平移:translationX、translationY
public void setTranslationX(float translationX) 
public void setTranslationY(float translationY)

//縮放:scaleX、scaleY
public void setScaleX(float scaleX)
public void setScaleY(float scaleY)
能夠看到在View中已經實現了有關alpha,rotaion,translate,scale相關的set方法。所以我們在構造ObjectAnimator時能夠直接使用。
在開始逐個看這些函數的使用方法前。我們先做一個總結:
1、要使用ObjectAnimator來構造對畫,要操作的控件中。必須存在相應的屬性的set方法
2、setter 方法的命名必須以駱駝拼寫法命名。即set后每一個單詞首字母大寫,其余字母小寫,即相似於setPropertyName所相應的屬性為propertyName

以下我們就來看一下上面中各個方法的使用方法及作用。
有關alpha的使用方法。上面已經講過了,以下我們來看看其他的

(1)、setRotationX、setRotationY與setRotation

  • setRotationX(float rotationX):表示環繞X軸旋轉,rotationX表示旋轉度數 
  • setRotationY(rotationY):表示環繞Y軸旋轉,rotationY表示旋轉度數 
  • setRotation(float rotation):表示環繞Z旋轉,rotation表示旋轉度數 
先來看看setRotationX的效果:
ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotationX",0,270,0);
animator.setDuration(2000);
animator.start();

效果圖例如以下:


從效果圖中明顯看出,textview的旋轉方法是環繞X軸旋轉的,我們設定為從0度旋轉到270度再返回0度。
然后再來看看setRotationY的使用方法與效果:

ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotationY",0,180,0);
animator.setDuration(2000);
animator.start();

效果圖例如以下:


從效果圖中明顯能夠看出環繞Y軸旋轉的。
我們再來看看setRotation的使用方法與效果:

ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,270,0);
animator.setDuration(2000);
animator.start();

我們上面說了,setRotation是環繞Z軸旋轉的,可能有些同學不理解什么是Z軸,我們來看一張圖:


從這張圖中,綠色框部分表示手機屏幕,非常明顯能夠看出Z軸就是從屏幕左上角原點向外伸出的一條軸。

這樣。我們也就能夠理解環繞Z軸旋轉。為什么是這樣子轉了。

(2)、setTranslationX與setTranslationY

  • setTranslationX(float translationX) :表示在X軸上的平移距離,以當前控件為原點,向右為正方向。參數translationX表示移動的距離。 
  • setTranslationY(float translationY) :表示在Y軸上的平移距離。以當前控件為原點。向下為正方向,參數translationY表示移動的距離。 
我們先看看setTranslationX的使用方法:

ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "translationX", 0, 200, -200,0);
animator.setDuration(2000);
animator.start();
效果圖例如以下:

所以。我們上面在構造動畫時,指定的移動距離是(0, 200, -200,0)。所以控件會從自身全部位置向右移動200像素,然后再移動到距離原點-200的位置,最后回到原點。
然后我們來看看setTranslateY的使用方法:

ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "translationY", 0, 200, -100,0);
animator.setDuration(2000);
animator.start();
效果圖例如以下:(為了方便看到效果。將textview垂直居中)

相同,移動位置的坐標也都是以當前控件所在位置為中心點的。所以相應的移動位置從原點移動向下移動200像素,然后再移動到向下到距原點200像素的位置,最后再回到(0,0)從效果圖中非常明顯能夠看出來。


從上面能夠看出:每次移動距離的計算都是以原點為中心的;比方初始動畫為ObjectAnimator.ofFloat(tv, “translationY”, 0, 200, -100,0)表示首先從0移動到正方向200的位置,然后再移動到負方向100的位置。最后移動到原點。


(3)、setScaleX與setScaleY

  • setScaleX(float scaleX):在X軸上縮放。scaleX表示縮放倍數 
  • setScaleY(float scaleY):在Y軸上縮放,scaleY表示縮放倍數 
我們來看看setScaleX的使用方法:

ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleX", 0, 3, 1);
animator.setDuration(2000);
animator.start();
效果圖例如以下:

在效果圖中,從0倍放大到3倍,然后再還原到1倍的原始狀態。
然后再來看看setScaleY的使用方法

ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleY", 0, 3, 1);
animator.setDuration(2000);
animator.start();
為了更好的看到效果,我把textview垂直居中了,效果圖例如以下:

源代碼在文章底部給出 
好了,到這里有關View中自帶的set函數講完了,我們來看看ObjectAnimator是怎樣實現控件動畫效果的。

3、ObjectAnimator動畫原理

我們先來看張圖:


在這張圖中,將ValueAnimator的動畫流程與ObjectAnimator的動畫流程做了個對照。


能夠看到ObjectAnimator的動畫流程中,也是首先通過加速器產生當前進度的百分比。然后再經過Evaluator生成相應百分比所相應的數字值。這兩步與ValueAnimator是全然一樣的,唯一不同的是最后一步。在ValueAnimator中,我們要通過加入監聽器來監聽當前數字值。而在ObjectAnimator中,則是先依據屬性值拼裝成相應的set函數的名字,比方這里的scaleY的拼裝方法就是將屬性的第一個字母強制大寫后,與set拼接,所以就是setScaleY。然后通過反射找到相應控件的setScaleY(float scaleY)函數,將當前數字值做為setScaleY(float scale)的參數將其傳入。
這里在找到控件的set函數以后。是通過反射來調用這個函數的,有關反射的使用大家能夠參考《夯實JAVA基本之二 —— 反射(1):基本類周邊信息獲取》
這就是ObjectAnimator的流程,最后一步總結起來就是調用相應屬性的set方法。將動畫當前數字值做為參數傳進去。


依據上面的流程,這里有幾個注意事項:
(1)、拼接set函數的方法:上面我們也說了是首先是強制將屬性的第一個字母大寫,然后與set拼接,就是相應的set函數的名字。

注意。僅僅是強制將屬性的第一個字母大寫,后面的部分是保持不變的。

反過來,假設我們的函數名命名為setScalePointX(float ),那我們在寫屬性時能夠寫成”scalePointX”或者寫成“ScalePointX”都是能夠的,即第一個字母大寫和小寫能夠任意。但后面的部分必須與set方法后的大寫和小寫保持一致。
(2)、怎樣確定函數的參數類型:上面我們知道了怎樣找到相應的函數名,那相應的參數方法的參數類型怎樣確定呢?我們在講ValueAnimator的時候說過。動畫過程中產生的數字值與構造時傳入的值類型是一樣的。因為ObjectAnimator與ValueAnimator在插值器和Evaluator這兩步是全然一樣的。而當前動畫數值的產生是在Evaluator這一步產生的,所以ObjectAnimator的動畫中產生的數值類型也是與構造時的類型一樣的。那么問題來了,像我們的構造方法。

ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleY", 0, 3, 1);
因為構造時使用的是ofFloat函數,所以中間值的類型應該是Float類型的,所以在最后一步拼裝出來的set函數應該是setScaleY(float xxx)的樣式;這時,系統就會利用反射來找到setScaleY(float xxx)函數,並把當前的動畫數值做為參數傳進去。


那問題來了。假設沒有相似setScaleY(float xxx)的函數,我們僅僅實現了一個setScaleY(int xxx)的函數怎么辦?這里盡管函數名一樣。但參數類型是不一樣的。那么系統就會報一個錯誤:

意思就是相應函數的指定參數類型沒有找到。
(3)、調用set函數以后怎么辦?從ObjectAnimator的流程能夠看到。ObjectAnimator僅僅負責把動畫過程中的數值傳到相應屬性的set函數中就結束了。注意傳給set函數以后就結束了。set函數就相當我們在ValueAnimator中加入的監聽的作用,set函數中的對控件的操作還是須要我們自己來寫的。

那我們來看看View中的setScaleY是怎么實現的吧:

/**
 * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
 * the view's unscaled width. A value of 1 means that no scaling is applied.
 *
 * @param scaleY The scaling factor.
 * @see #getPivotX()
 * @see #getPivotY()
 *
 * @attr ref android.R.styleable#View_scaleY
 */
public void setScaleY(float scaleY) {
    ensureTransformationInfo();
    final TransformationInfo info = mTransformationInfo;
    if (info.mScaleY != scaleY) {
        invalidateParentCaches();
        // Double-invalidation is necessary to capture view's old and new areas
        invalidate(false);
        info.mScaleY = scaleY;
        info.mMatrixDirty = true;
        mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
        invalidate(false);
    }
}
大家不必理解這一坨代碼的意義,因為這些代碼是須要讀懂View的總體流程以后才干看得懂的。僅僅須要跟着我的步驟來理解即可。這段代碼總共分為兩部分:第一步又一次設置當前控件的參數,第二步調用Invalidate()強制重繪。
所以在重繪時,控件就會依據最新的控件參數來繪制了,所以我們就看到當前控件被縮放了。
(4)、set函數調用頻率是多少:因為我們知道動畫在進行時,每隔十幾毫秒會刷新一次,所以我們的set函數也會每隔十幾毫秒會被調用一次。
講了這么多,就是為了強調一點:ObjectAnimator僅僅負責把當前運動動畫的數值傳給set函數。至於set函數里面怎么來做。是我們自己的事了。
好了,在知道了ObjectAnimator的原理以后,以下就來看看怎樣自己定義一個ObjectAnimator的屬性吧。

二、自己定義ObjectAnimator屬性

上面我們已經看了使用View自帶的set函數所相應屬性的方法,並且理解了ObjectAnimator的動畫實現原理,以下我們來自己定義一個屬性來看看實現效果吧。
我們在開始之前再來捋一下ObjectAnimator的動畫設置流程:ObjectAnimator須要指定操作的控件對象,在開始動畫時,到控件類中去尋找設置屬性所相應的set函數。然后把動畫中間值做為參數傳給這個set函數並運行它。
所以。我們說了,控件類中必須所要設置屬性所要相應的set函數。所以為了自由控制控件的實現,我們這里自己定義一個控件。大家知道在這個自己定義控件中,肯定存在一個set函數與我們自己定義的屬性相相應。
我們先來看看這段要實現的效果:

這個效果圖與我們上篇自己定義控件實現的效果幾乎相同,這個控件中存在一個圓形。也是在動畫時先將這個圓形放大,然后再將圓形還原。

1、保存圓形信息類——Point

為了,保存圓形的信息,我們先定義一個類:(Point.java)

public class Point {
    private int mRadius;

    public Point(int radius){
        mRadius = radius;
    }

    public int getRadius() {
        return mRadius;
    }

    public void setRadius(int radius) {
        mRadius = radius;
    }
}
這個類非常好理解,僅僅有一個成員變量mRadius,表示圓的半徑。

2、自己定義控件——MyPointView

然后我們自己定義一個控件MyPointView,完整代碼例如以下:
public class MyPointView extends View {
    private Point mPoint = new Point(100);

    public MyPointView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mPoint != null){
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setColor(Color.RED);
            paint.setStyle(Paint.Style.FILL);
            canvas.drawCircle(300,300,mPoint.getRadius(),paint);
        }
        super.onDraw(canvas);
    }

    void setPointRadius(int radius){
        mPoint.setRadius(radius);
        invalidate();
    }

}
在這段代碼中,首先來看我們前面講到的set函數:
void setPointRadius(int radius){
    mPoint.setRadius(radius);
    invalidate();
}
第一點,這個set函數所相應的屬性應該是pointRadius或者PointRadius。前面我們已經講了第一個字母大寫和小寫無所謂,后面的字母必須保持與set函數全然一致。
第二點,在setPointRadius中,先將當前動畫傳過來的值保存到mPoint中。做為當前圓形的半徑。

然后強制界面刷新
在界面刷新后。就開始運行onDraw()函數:

@Override
protected void onDraw(Canvas canvas) {
    if (mPoint != null){
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(300,300,mPoint.getRadius(),paint);
    }
    super.onDraw(canvas);
}
在onDraw函數中,就是依據當前mPoint的半徑值在(300,300)點外畫一個圓;有關畫圓的知識。大家能夠參考《android Graphics(一):概述及基本幾何圖形繪制》

3、使用MyPointView

首先,在MyActivity的布局中加入MyPointView的使用(main.xml):
<?xml version="1.0" encoding="utf-8"?

> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:padding="10dp" android:text="start anim" /> <Button android:id="@+id/btn_cancel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:padding="10dp" android:text="cancel anim" /> <TextView android:id="@+id/tv" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:gravity="center" android:padding="10dp" android:background="#ffff00" android:text="Hello qijian"/> <com.example.BlogObjectAnimator1.MyPointView android:id="@+id/pointview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/tv"/> </RelativeLayout>

布局代碼非常好理解。依據效果圖中的布局效果來理解。非常easy,就不再多講
然后看看在MyActivity中,點擊start anim后的處理方法:
public class MyActivity extends Activity {
    private Button btnStart;
    private MyPointView mPointView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btnStart = (Button) findViewById(R.id.btn);
        mPointView = (MyPointView)findViewById(R.id.pointview);

        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                doPointViewAnimation();
            }
        });
    }
  …………
}     
在點擊start animbutton后。開始運行doPointViewAnimation()函數,doPointViewAnimation()函數代碼例如以下:
private void doPointViewAnimation(){
     ObjectAnimator animator = ObjectAnimator.ofInt(mPointView, "pointRadius", 0, 300, 100);
      animator.setDuration(2000);
      animator.start();
}
在這段代碼中。着重看ObjectAnimator的構造方法,首先要操作的控件對象是mPointView,然后相應的屬性是pointRadius,然后值是從0到300再到100;
所以在動畫開始以后。ObjectAnimator就會實時地把動畫中產生的值做為參數傳給MyPointView類中的setPointRadius(int radius)函數,然后調用setPointRadius(int radius)。因為我們在setPointRadius(int radius)中實時地設置圓形的半徑值然后強制重繪當前界面,所以能夠看到圓形的半徑會隨着動畫的進行而改變。


源代碼在文章底部給出

四、注意——何時須要實現相應屬性的get函數

我們再來看一下ObjectAinimator的以下三個構造方法:
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
public static ObjectAnimator ofInt(Object target, String propertyName, int... values)
public static ObjectAnimator ofObject(Object target, String propertyName,TypeEvaluator evaluator, Object... values)
前面我們已經分別講過三個函數的使用方法,在上面的三個構造方法中最后一個參數都是可變長參數。我們也講了,他們的意義就是從哪個值變到哪個值的。
那么問題來了:前面我們都是定義多個值,即至少兩個值之間的變化,那假設我們僅僅定義一個值呢,如以下的方式:(相同以MyPointView為例)
ObjectAnimator animator = ObjectAnimator.ofInt(mPointView, "pointRadius",100);
我們在這里僅僅傳遞了一個變化值100;那它從哪里開始變化呢?我們來看一下效果:
代碼例如以下:
ObjectAnimator animator = ObjectAnimator.ofInt(mPointView, "pointRadius",100);
animator.setDuration(2000);
animator.start();
效果圖例如以下:

從效果圖中看起來是從0開始的。可是看log能夠看出來已經在出警告了:

我們點了三次start animbutton。所以這里也報了三次,意思就是沒找到pointRadius屬性所相應的getPointRadius()函數;
僅且僅當我們僅僅給動畫設置一個值時,程序才會調用屬性相應的get函數來得到動畫初始值。假設動畫沒有初始值,那么就會使用系統默認值。比方ofInt()中使用的參數類型是int類型的,而系統的Int值的默認值是0,所以動畫就會從0運動到100;也就是系統盡管在找到不到屬性相應的get函數時,會給出警告,但同一時候會用系統默認值做為動畫初始值。


假設通過給自己定義控件MyPointView設置了get函數,那么將會以get函數的返回值做為初始值:

public class MyPointView extends View {
    private Point mPoint = new Point(100);

    public MyPointView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mPoint != null){
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setColor(Color.RED);
            paint.setStyle(Paint.Style.FILL);
            canvas.drawCircle(300,300,mPoint.getRadius(),paint);
        }
        super.onDraw(canvas);
    }

    public int getPointRadius(){
        return 50;
    }

    public void setPointRadius(int radius){
        mPoint.setRadius(radius);
        invalidate();
    }

}
我們在這里加入了getPointRadius函數,返回值是Int.有些同學可能會疑惑:我怎么知道這里要返回int值呢?
我們前面說過當且僅當我們在創建ObjectAnimator時,僅僅給他傳遞了一個過渡值的時候,系統才會調用屬性相應的get函數來得到動畫的初始值!所以做為動畫的初始值,那么在創建動畫時過渡值傳的什么類型,這里的get函數就要返回類型
public static ObjectAnimator ofObject(Object target, String propertyName,TypeEvaluator evaluator, Object... values)
比方上面的ofObject,get函數所返回的類型就是與最后一個參數Object... values,相同類型的。


在我們在MyPointView加入上PointRadius所相應的get函數以后又一次運行動畫:

ObjectAnimator animator = ObjectAnimator.ofInt(mPointView, "pointRadius",100);
animator.setDuration(2000);
animator.start();
此時的效果圖例如以下:

從動畫中能夠看出。半徑已經不是從0開始的了,而是從50開始的。
最后我們總結一下:當且僅當動畫的僅僅有一個過渡值時,系統才會調用相應屬性的get函數來得到動畫的初始值。

源代碼在文章底部給出

三、經常使用函數

有關經常使用函數這一節事實上沒有太多講的必要。

因為ObjectAnimator的函數都是從ValueAnimator中繼承而來的。所以使用方法和效果與ValueAnimator是全然一樣的。我們這里僅僅解說一下Evaluator的使用方法,其他的也就不再講了。

1、使用ArgbEvaluator

我們搜一下TextView全部的函數發現,TextView有一個set函數能夠改變背景色:
public void setBackgroundColor(int color);
大家能夠回想到,我們在ValueAnimator中也曾改變過背景色,使用的是ArgbEvaluator。在這里我們再回想下ArgbEvaluator,它的實現代碼例如以下:
public class ArgbEvaluator implements TypeEvaluator {
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        int startInt = (Integer) startValue;
        int startA = (startInt >> 24);
        int startR = (startInt >> 16) & 0xff;
        int startG = (startInt >> 8) & 0xff;
        int startB = startInt & 0xff;

        int endInt = (Integer) endValue;
        int endA = (endInt >> 24);
        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))));
    }
}
有關它具體實現的原理。前面篇章中我們已經講過了,這里主要說一點。ArgbEvaluator的返回值是Integer類型,所以我們要使用ArgbEvaluator的話,構造ObjectAnimator時必須使用ofInt()
以下我們來看看使用ArgbEvaluator的代碼:
ObjectAnimator animator = ObjectAnimator.ofInt(tv, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff);
animator.setDuration(8000);
animator.setEvaluator(new ArgbEvaluator());
animator.start();
然后我們來看下代碼效果:

源代碼在文章底部給出

2、其他函數

以下把其他所涉及到的函數的列表列在以下。大家能夠參考ValueAnimator的使用方法來使用。有關自己定義插值器和Evaluator的部分,能夠參考《Animation動畫具體解釋(五)——高級進階(一)》

(1)、經常使用函數

/**
 * 設置動畫時長,單位是毫秒
 */
ValueAnimator setDuration(long duration)
/**
 * 獲取ValueAnimator在運動時。當前運動點的值
 */
Object getAnimatedValue();
/**
 * 開始動畫
 */
void start()
/**
 * 設置循環次數,設置為INFINITE表示無限循環
 */
void setRepeatCount(int value)
/**
 * 設置循環模式
 * value取值有RESTART,REVERSE,
 */
void setRepeatMode(int value)
/**
 * 取消動畫
 */
void cancel()

(2)、監聽器相關

/**
 * 監聽器一:監聽動畫變化時的實時值
 */
public static interface AnimatorUpdateListener {
    void onAnimationUpdate(ValueAnimator animation);
}
//加入方法為:public void addUpdateListener(AnimatorUpdateListener listener)
/**
 * 監聽器二:監聽動畫變化時四個狀態
 */
public static interface AnimatorListener {
    void onAnimationStart(Animator animation);
    void onAnimationEnd(Animator animation);
    void onAnimationCancel(Animator animation);
    void onAnimationRepeat(Animator animation);
}
//加入方法為:public void addListener(AnimatorListener listener) 

(3)、插值器與Evaluator

/**
 * 設置插值器
 */
public void setInterpolator(TimeInterpolator value)
/**
 * 設置Evaluator
 */
public void setEvaluator(TypeEvaluator value)
到這里,有關ObjectAnimator的知識就講完了,下篇再講講聯合動畫和xml中實現動畫的方法。

假設本文有幫到你,記得加關注哦

源代碼下載地址:

csdn:http://download.csdn.net/detail/harvic880925/9445785

github:https://github.com/harvic/BlogResForGitHub

請大家尊重原創者版權,轉載請標明出處,謝謝


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM