1. 程式人生 > >Android自定義view之屬性動畫一

Android自定義view之屬性動畫一

Android 裡動畫是有一些分類的:動畫可以分為兩類:Animation 和 Transition;其中 Animation 又可以再分為 View Animation 和 Property Animation 兩類: View Animation 是純粹基於 framework 的繪製轉變,比較簡單,如果你有興趣的話可以上網搜一下它的用法;Property Animation,屬性動畫,這是在 Android 3.0 開始引入的新的動畫形式,不過說它新只是相對的,它已經有好幾年的歷史了,而且現在的專案中的動畫 99% 都是用的它,極少再用到 View Animation 了。屬性動畫不僅可以使用自帶的 API 來實現最常用的動畫,而且通過自定義 View 的方式來做出定製化的動畫。除了這兩種 Animation,還有一類動畫是 Transition。 Transition 這個詞的本意是轉換,在 Android 裡指的是切換介面時的動畫效果,這個在邏輯上要複雜一點,不過它的重點是在於切換而不是動畫,所以它也不是這次要討論的內容。這次的內容只專注於一點:Property Animation(屬性動畫)

我們做屬性動畫的時候用兩種

一、ViewPropertyAnimator

 使用方式:View.animate() 後跟 translationX() 等方法,動畫會自動執行。

view.animate().translationX(500);  

具體可以跟的方法以及方法所對應的 View 中的實際操作的方法如下圖所示:

從圖中可以看到, View 的每個方法都對應了 ViewPropertyAnimator 的兩個方法,其中一個是帶有 -By 字尾的,例如,View.setTranslationX() 對應了 ViewPropertyAnimator.translationX()

 和 ViewPropertyAnimator.translationXBy() 這兩個方法。其中帶有 -By() 字尾的是增量版本的方法,例如,translationX(100) 表示用動畫把 View 的 translationX 值漸變為 100,而 translationXBy(100) 則表示用動畫把 View 的 translationX 值漸變地增加 100。l

二、ObjectAnimator

使用方式:

  1. 如果是自定義控制元件,需要新增 setter / getter 方法;
  2. 用 ObjectAnimator.ofXXX() 建立 ObjectAnimator 物件;
  3. 用 start()
     方法執行動畫。
public class SportsView extends View {  

    float progress = 0;

    ......

    // 建立 getter 方法
    public float getProgress() {
        return progress;
    }

    // 建立 setter 方法
    public void setProgress(float progress) {
        this.progress = progress;
        invalidate();
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        ......

        canvas.drawArc(arcRectF, 135, progress * 2.7f, false, paint);

        ......
    }
}

......

// 建立 ObjectAnimator 物件
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "progress", 0, 65);  //自定義progress屬性
// 執行動畫
animator.start();  

 

這裡一定要記得寫 屬性的 getter和setter 因為animator 會根據getter獲得屬性值 然後根據setter不斷的去設定屬性值 已達到變化的效果

通用功能

1. setDuration(int duration) 設定動畫時長

// imageView1: 500 毫秒
imageView1.animate()  
        .translationX(500)
        .setDuration(500);

// imageView2: 2 秒
ObjectAnimator animator = ObjectAnimator.ofFloat(  
        imageView2, "translationX", 500);
animator.setDuration(2000);  
animator.start();  

設定了動畫時長後 動畫會自動根據時長來調節動畫執行速度 所以這個是很好的設定速度的方法 

2. setInterpolator(Interpolator interpolator) 設定 Interpolator

// imageView1: 線性 Interpolator,勻速
imageView1.animate()  
        .translationX(500)
        .setInterpolator(new LinearInterpolator());

// imageView: 帶施法前搖和回彈的 Interpolator
ObjectAnimator animator = ObjectAnimator.ofFloat(  
        imageView2, "translationX", 500);
animator.setInterpolator(new AnticipateOvershootInterpolator());  
animator.start();  

可以為動畫設定插值器 接控制動畫的變化速率,這涉及到變化率概念,形象點說就是加速度,可以簡單理解為變化的快慢

比較常用的有下面四個:

  • 加減速插值器AccelerateDecelerateInterpolator
  • 線性插值器LinearInterpolator
  • 加速插值器AccelerateInterpolator
  • 減速插值器DecelerateInterpolator

3. 設定監聽器

給動畫設定監聽器,可以在關鍵時刻得到反饋,從而及時做出合適的操作,例如在動畫的屬性更新時同步更新其他資料,或者在動畫結束後回收資源等。

設定監聽器的方法, ViewPropertyAnimator 和 ObjectAnimator 略微不一樣: ViewPropertyAnimator 用的是 setListener() 和 setUpdateListener() 方法,可以設定一個監聽器,要移除監聽器時通過 set[Update]Listener(null) 填 null 值來移除;而 ObjectAnimator 則是用 addListener() 和 addUpdateListener() 來新增一個或多個監聽器,移除監聽器則是通過 remove[Update]Listener() 來指定移除物件。

另外,由於 ObjectAnimator 支援使用 pause() 方法暫停,所以它還多了一個 addPauseListener() / removePauseListener() 的支援;而 ViewPropertyAnimator 則獨有 withStartAction() 和 withEndAction() 方法,可以設定一次性的動畫開始或結束的監聽。

3.1 ViewPropertyAnimator.setListener() / ObjectAnimator.addListener()

這兩個方法的名稱不一樣,可以設定的監聽器數量也不一樣,但它們的引數型別都是 AnimatorListener,所以本質上其實都是一樣的。 AnimatorListener 共有 4 個回撥方法:

3.1.1 onAnimationStart(Animator animation)

當動畫開始執行時,這個方法被呼叫。

3.1.2 onAnimationEnd(Animator animation)

當動畫結束時,這個方法被呼叫。

3.1.3 onAnimationCancel(Animator animation)

當動畫被通過 cancel() 方法取消時,這個方法被呼叫。

需要說明一下的是,就算動畫被取消,onAnimationEnd() 也會被呼叫。所以當動畫被取消時,如果設定了 AnimatorListener,那麼 onAnimationCancel() 和 onAnimationEnd() 都會被呼叫。onAnimationCancel() 會先於 onAnimationEnd() 被呼叫。

3.1.4 onAnimationRepeat(Animator animation)

當動畫通過 setRepeatMode() / setRepeatCount() 或 repeat() 方法重複執行時,這個方法被呼叫。

由於 ViewPropertyAnimator 不支援重複,所以這個方法對 ViewPropertyAnimator 相當於無效。

3.2 ViewPropertyAnimator.setUpdateListener() / ObjectAnimator.addUpdateListener()

和上面 3.1 的兩個方法一樣,這兩個方法雖然名稱和可設定的監聽器數量不一樣,但本質其實都一樣的,它們的引數都是 AnimatorUpdateListener。它只有一個回撥方法:onAnimationUpdate(ValueAnimator animation)

3.2.1 onAnimationUpdate(ValueAnimator animation)

當動畫的屬性更新時(不嚴謹的說,即每過 10 毫秒,動畫的完成度更新時),這個方法被呼叫。

方法的引數是一個 ValueAnimatorValueAnimator 是 ObjectAnimator 的父類,也是 ViewPropertyAnimator的內部實現,所以這個引數其實就是 ViewPropertyAnimator 內部的那個 ValueAnimator,或者對於 ObjectAnimator 來說就是它自己本身。

ValueAnimator 有很多方法可以用,它可以檢視當前的動畫完成度、當前的屬性值等等。不過 ValueAnimator 是下一期才講的內容,所以這期就不多說了。

3.3 ObjectAnimator.addPauseListener()

由於 ObjectAnimator.pause() 是下期的內容,所以這個方法在這期就不講了。當然,如果你有興趣的話,現在就瞭解一下也可以。

3.3 ViewPropertyAnimator.withStartAction/EndAction()

這兩個方法是 ViewPropertyAnimator 的獨有方法。它們和 set/addListener() 中回撥的 onAnimationStart() / onAnimationEnd() 相比起來的不同主要有兩點:

  1. withStartAction() / withEndAction() 是一次性的,在動畫執行結束後就自動棄掉了,就算之後再重用 ViewPropertyAnimator 來做別的動畫,用它們設定的回撥也不會再被呼叫。而 set/addListener() 所設定的 AnimatorListener 是持續有效的,當動畫重複執行時,回撥總會被呼叫。

  2. withEndAction() 設定的回撥只有在動畫正常結束時才會被呼叫,而在動畫被取消時不會被執行。這點和 AnimatorListener.onAnimationEnd() 的行為是不一致的。

文章內容採摘來自HenCoder  本文主做於學習總結 感謝HenCoder