學習,參考加部分信息拷貝,來自以下鏈接:
動畫原理講解系列:
http://blog.csdn.net/u013478336/article/details/52137385
牛逼的自定義插值器:
http://www.cnblogs.com/wondertwo/p/5327586.html
Evaluator
http://wiki.jikexueyuan.com/project/android-animation/5.html
http://wiki.jikexueyuan.com/project/android-animation/6.html 講evaluator字母的變化
牛逼的動畫原理講解,但是沒有仔細看的:
http://www.lxweimin.com/p/ee7e3d79006d
其他:
http://www.lxweimin.com/p/733532041f46
http://blog.csdn.net/lmj623565791/article/details/38067475/
概述
1.1 簡述
屬性動畫引入自Android 3.0(API 11),其原理是給定對象的一個或多個屬性,指定其開始與結束時的值,通過時間插值生成不同的屬性值,并調用更新方法將屬性值設置到對象內,引起對象重繪,從而形成動畫效果。比如,通過不斷的設置View的寬高來更新View的展示,形成縮放效果等。
1.2 屬性動畫相關概念
一個屬性動畫執行需要的基本要素包括:承載動畫執行的對象屬性、動畫持續時間和屬性的變化區間。
- Duration: 指定動畫的執行時間,默認300ms
- Time interpolation: 一個輸入為動畫真實時間的函數,以此函數來計算動畫屬性;其實重點在于函數上,這個函數定義的是動畫的變化速率,舉個例子來看:假如有個函數y=x,x是動畫的真實執行時間,y是映射后的速度,則這個動畫是恒速執行的;假如映射函數是y=x*x,這個動畫是就是不斷加速運行的,因為y的變化速率在不斷的增大。
- Repeat count and behavior: 動畫重復次數表示動畫需要被執行的次數,動畫重復時的行為有兩種:從頭開始或者反轉執行;在動畫執行結束時,如果沒有執行完指定次數,則繼續執行;
- Animator sets: 將多個動畫效果組成動畫集合并設置彼此間的執行順序,可設三種執行順序:一起執行、順序執行和在指定時間執行。
- Frame refresh delay: 指定多長時間刷新一次動畫的幀,默認值是10ms一次,但最終取決于當前系統的繁忙程度和系統多快能相應定時器,基本上我們可以不用考慮。
- 監聽動畫: 開始 / 結束 / 重復時刻
anim.addListener(new AnimatorListenerAdapter() {
// 向addListener()方法中傳入適配器對象AnimatorListenerAdapter()
// 由于AnimatorListenerAdapter中已經實現好每個接口
// 所以這里不實現全部方法也不會報錯
@Override
public void onAnimationStart(Animator animation) {
// 如想只想監聽動畫開始時刻,就只需要單獨重寫該方法就可以
}
});
1.3 屬性動畫與補間動畫的區別
應用對象不同,本質不同,適用范圍有包含關系。
- 補間動畫的應用對象只能是View,不能用于非View對象,屬性動畫支持任意對象;
- 補間動畫的本質是對View做Transformation,并不能影響View的布局位置,只能影響View的可視位置。如果View從屏幕左邊移動到右邊,則其展示在右邊了,但是這時候View相應點擊事件還是在左邊的位置,因為View并沒有真的移動到右邊,只是被繪制到右邊了;
- 及時動畫對象是View,補間動畫能做的也比較有限,只能做平移/旋轉/縮放/透明度四種變化效果,假如我們要不斷改變View背景色,就搞不定了,屬性動畫表示毫無壓力;
- 屬性動畫比補間動畫更靈活,可以同時支持多個屬性的動畫,每個屬性都可以獨立定義插值器,各動畫之間還可以做動畫同步控制。
1.4 Interpolator vs evaluator
- Interpolator: 插值器, 用來定義animator變化的速率 (加速、減速...)
AccelerateDecelerateInterpolator 在動畫開始與結束的地方速率改變比較慢,在中間的時候加速
AccelerateInterpolator 在動畫開始的地方速率改變比較慢,然后開始加速
AnticipateInterpolator 開始的時候向后然后向前甩
AnticipateOvershootInterpolator 開始的時候向后然后向前甩一定值后返回最后的值
BounceInterpolator 動畫結束的時候彈起
CycleInterpolator 動畫循環播放特定的次數,速率改變沿著正弦曲線
DecelerateInterpolator 在動畫開始的時候快然后慢
LinearInterpolator 以常量速率改變
OvershootInterpolator 向前甩一定值后再回到原來位置
-
evaluator: 返回動畫在當前時間點所需要的值
我們可以把動畫的過程想象成是一部電影的播放,電影的播放中有進度條,Interpolator就是用來控制電影播放頻率,也就是快進快退要多少倍速。然后Evaluator根據Interpolator提供的值(fraction)計算當前播放電影中的哪一個畫面,也就是進度條要處于什么位置。
1.5 動畫的過程中所涉及的計算
ValueAnimator對象會根據動畫的總時間和已經流逝的時間計算出一個0到1之間的elapsed fraction值。這個elapsed fraction值就代表了時間完成的程度
計算出elapsed fraction之后,ValueAnimator對象會調用TimeInterpolator
來計算一個interpolated fraction,即,根據所設置的時間插值方法將elapsed fraction映射到interpolated fraction。 interpolated fraction 可能大于、小于、等于elapsed fraction,就看使用的什么插值器了。interpolated fraction計算出來后,ValueAnimator 會調用TypeEvaluator,來進行你要動畫的屬性值的計算。
這時候用的輸入參數就是interpolated fraction的值,以及屬性值的起始值和終止值。
ValueAnimator
- 構造
ValueAnimator.ofArgb
ValueAnimator.ofInt
ValueAnimator.ofFloat
ValueAnimator.ofObject
ValueAnimator.ofPropertyValuesHolder
ValueAnimator animator = ValueAnimator.ofInt(0, 400);
animator.setDuration(1000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int) animation.getAnimatedValue();
tv.layout(curValue, curValue, curValue + tv.getWidth(), curValue + tv.getHeight());
}
});
animator.start();
PropertyValuesHolder
- 保存了動畫過程中所需要操作的屬性和對應的值。
- 我們通過 ofInt(Object target, String propertyName, int… values)構造的動畫,ofInt()的內部實現其實就是將傳進來的參數封裝成 PropertyValuesHolder 實例來保存動畫狀態。
- 在封裝成 PropertyValuesHolder 實例以后,后期的各種操作也是以 PropertyValuesHolder 為主的。
自定義ValueAnimator
ObjectAnimator
ValueAnimator 有個缺點,就是只能對數值對動畫計算。想對哪個控件操作,需要監聽動畫過程,在監聽中對控件操作。
為了能讓動畫直接與對應控件相關聯,以使我們從監聽動畫過程中解放出來在 ValueAnimator 的基礎上,又派生了一個類 ObjectAnimator;
先看看利用 ObjectAnimator 重寫的 ofFloat 方法如何實現一個動畫:(改變透明度)
ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"alpha",1,0,1);
animator.setDuration(2000);
animator.start();
- 要使用 ObjectAnimator 來構造對畫,要操作的控件中,必須存在對應的屬性的 set 方法
- setter 方法的命名必須以駱駝拼寫法命名,即 set 后每個單詞首字母大寫,其余字母小寫,即類似于 setPropertyName 所對應的屬性為 propertyName ;
set 函數調用頻率是多少:動畫在進行時,每隔十幾毫秒會刷新一次,所以我們的 set 函數也會每隔十幾毫秒會被調用一次。
系統會根據屬性通過反射找到對應屬性的設置方法,刷新其值 - 何時需要實現對應屬性的 get 函數。構造方法中最后一個參數都是可變長參數,從哪個值變到哪個值的,如果值傳入了一個值,那默認值最終值,起始值就從get屬性獲取。
**自定義ObjectAnimator **
AnimatorSet
- AnimatorSet 針對 ValueAnimator 和 ObjectAnimator 都是適用的;
- playSequentially 表示所有動畫依次播放,playTogether 表示所有動畫一起開始。
- setTarget屬性,在 AnimatorSet 中設置以后,會覆蓋單個 ObjectAnimator 中的設置;即如果 AnimatorSet 中沒有設置,那么就以 ObjectAnimator 中的設置為準。
自定義Interpolator
public class AccelerateDecelerateInterpolator extends BaseInterpolator
implements NativeInterpolatorFactory {
public AccelerateDecelerateInterpolator() {
}
@SuppressWarnings({"UnusedDeclaration"})
public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) {
}
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
/** @hide */
@Override
public long createNativeInterpolator() {
return NativeInterpolatorFactoryHelper.createAccelerateDecelerateInterpolator();
}
}
換成數學表達式
{0.5*cos[(input + 1)π] + 0.5}
在0-1之間,增長速度是先變快,后勻速,最后慢慢變慢