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
使用方式:
- 如果是自定義控制元件,需要新增
setter
/getter
方法; - 用
ObjectAnimator.ofXXX()
建立ObjectAnimator
物件; - 用
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 毫秒,動畫的完成度更新時),這個方法被呼叫。
方法的引數是一個 ValueAnimator
,ValueAnimator
是 ObjectAnimator
的父類,也是 ViewPropertyAnimator
的內部實現,所以這個引數其實就是 ViewPropertyAnimator
內部的那個 ValueAnimator
,或者對於 ObjectAnimator
來說就是它自己本身。
ValueAnimator
有很多方法可以用,它可以檢視當前的動畫完成度、當前的屬性值等等。不過 ValueAnimator
是下一期才講的內容,所以這期就不多說了。
3.3 ObjectAnimator.addPauseListener()
由於 ObjectAnimator.pause()
是下期的內容,所以這個方法在這期就不講了。當然,如果你有興趣的話,現在就瞭解一下也可以。
3.3 ViewPropertyAnimator.withStartAction/EndAction()
這兩個方法是 ViewPropertyAnimator
的獨有方法。它們和 set/addListener()
中回撥的 onAnimationStart()
/ onAnimationEnd()
相比起來的不同主要有兩點:
-
withStartAction()
/withEndAction()
是一次性的,在動畫執行結束後就自動棄掉了,就算之後再重用ViewPropertyAnimator
來做別的動畫,用它們設定的回撥也不會再被呼叫。而set/addListener()
所設定的AnimatorListener
是持續有效的,當動畫重複執行時,回撥總會被呼叫。 -
withEndAction()
設定的回撥只有在動畫正常結束時才會被呼叫,而在動畫被取消時不會被執行。這點和AnimatorListener.onAnimationEnd()
的行為是不一致的。