3.ValueAnimator 屬性動畫

動畫介紹:

  • 在Android動畫中,總共有兩種類型的動畫View Animation(視圖動畫)和Property Animator(屬性動畫)背犯;
  • View Animation包括Tween Animation(補間動畫)和Frame Animation(逐幀動畫)匀油;
    Property Animator包括ValueAnimator和ObjectAnimation浴栽;

區(qū)別:

  • View Animation僅能對指定的控件做動畫做盅,而Property Animator是通過改變控件某一屬性值來做動畫的最冰。
  • 補間動畫雖能對控件做動畫匣缘,但并沒有改變控件內(nèi)部的屬性值猖闪。而Property Animator則是恰恰相反,Property Animator是通過改變控件內(nèi)部的屬性值來達到動畫效果的肌厨。

屬性動畫:

ValueAnimator

  • 注意:單從名字上就可以看出來培慌,這個Animator是針對數(shù)值進行操作的,不對控件做操作柑爸〕郴ぃ控件和它并沒有什么關(guān)系,重點在數(shù)值上的操作表鳍。
  • 兩點:
    • ValueAnimator只負責(zé)對指定數(shù)值區(qū)間馅而,進行運算。
    • 自己需要對運算進行監(jiān)聽譬圣,然后自己對控件進行操作瓮恭。
ValueAnimator animator = ValueAnimator.ofInt(0,400);  
animator.setDuration(1000);  
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
    @Override  
    public void onAnimationUpdate(ValueAnimator animation) {  
        //拿到監(jiān)聽結(jié)果,自己處理厘熟。
        int curValue = (int)animation.getAnimatedValue(); 
        tvTextView.layout(curValue,curValue,curValue+tv.getWidth(),curValue+tv.getHeight());
    }  
});  
animator.start();  
常用方法和監(jiān)聽:
  • 方法:和Animation差不多屯蹦,看文檔。
  • 監(jiān)聽:
    • AnimatorUpdateListener:監(jiān)聽動畫變化時的實時值绳姨。addUpdateListener(AnimatorUpdateListener listener)登澜。
    • AnimatorListener:監(jiān)聽動畫變化時四個狀態(tài)。addListener(AnimatorListener listener)飘庄。
  • 移除監(jiān)聽:
/** 
 * 移除AnimatorUpdateListener 
 */  
void removeUpdateListener(AnimatorUpdateListener listener);  
void removeAllUpdateListeners();  
 /** 
  * 移除AnimatorListener 
  */  
void removeListener(AnimatorListener listener);  
void removeAllListeners();  

查看這段代碼:

ValueAnimator animator = ValueAnimator.ofInt(0,600); 
animator.setDuration(1000);  
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
    @Override  
    public void onAnimationUpdate(ValueAnimator animation) {  
        int curValue = (int)animation.getAnimatedValue();  
    }  
});  
animator.setInterpolator(new LinearInterpolator());  
animator.start();  
上面代碼中脑蠕,在1000毫秒的時間中,ValueAnimator的功能是竭宰,使數(shù)值從0到600根據(jù)插值器的類型去變化空郊。 (int)animation.getAnimatedValue()得到的是0~600之間的值,這個數(shù)值的獲取是Interpolator和Evalutor作用的結(jié)果切揭。
  • 0~600得到的值是否是勻速變化還是其他速度變化的狞甚,由Interpolator決定。
  • animation.getAnimatedValue()得到的值是多少廓旬,什么類型由Evalutor決定哼审。
inInt(0,600) 加速器 估值器 監(jiān)聽器返回
設(shè)置數(shù)值區(qū)間 Interpolator動畫比例 根據(jù)加速器的動畫比例算出實際值 getAnimatedValue得到實際值

插值器/加速器 Interpolator

  • 默認每10毫秒刷新一次
    //線性加速器
public class LinearInterpolator implements Interpolator {  
    public LinearInterpolator() {}  
    public LinearInterpolator(Context context, AttributeSet attrs) {}  
    public float getInterpolation(float input) {  
        return input;  
    }  
}  
public interface Interpolator extends TimeInterpolator {}  

參數(shù)input:是一個float類型谐腰,它取值范圍是0到1,表示當(dāng)前動畫的進度涩盾,取0時表示動畫剛開始十气,取1時表示動畫結(jié)束,取0.5時表示動畫中間的位置春霍,其它類推砸西。
返回值:表示當(dāng)前實際想要顯示的進度。取值可以超過1也可以小于0址儒,超過1表示已經(jīng)超過目標(biāo)值芹枷,小于0表示小于開始位置。

再重復(fù)一遍莲趣,input參數(shù)與任何我們設(shè)定的值沒關(guān)系鸳慈,只與時間有關(guān),隨著時間的增長喧伞,動畫的進度也自然的增加走芋,input參數(shù)就代表了當(dāng)前動畫的進度。而返回值則表示自定義后的動畫的當(dāng)前數(shù)值進度潘鲫。

上面代碼:為什么LinearInterpolator是線性勻速變化的呢翁逞?
因為插值器根據(jù)設(shè)置的總時間,每10ms刷新一次次舌,調(diào)用getInterpolation傳入當(dāng)前的進度熄攘,LinearInterpolator中原值返回了,沒有改變默認進度彼念。

看自定義加速器代碼對比:
public class MyInterpolator implements Interpolator {
    /**
     * input 是實際動畫執(zhí)行的時間比例 0~1
     * newInput 你想讓動畫已經(jīng)執(zhí)行的比例 0~1。
     * 注意:都是比例浅萧,而不是實際的值逐沙。
     * 
     * setDuration(1000)情況下:前200ms走了3/4的路程比例,后800ms走了1/4的路程比例洼畅。
     * 注意:這里輸出的是比例吩案,是路程比例,不是實際的路程值帝簇!
     */
    @Override
    public float getInterpolation(float input) {
        if (input <= 0.2) {//后1/4的時間徘郭,輸出3/4的比例
            float newInput = input*4;
            return newInput;
        }else {//后3/4的時間,輸出1/4的比例
            float newInput = (float) (input - 0.2)/4 + 0.8f;
            return newInput;
        }
    }
}

Evaluator 估值器

我們通過加速器得到的是動畫進度的比例丧肴,并不是實際的數(shù)值残揉,Evaluator就是轉(zhuǎn)換成實際值的地方。(ofInt(0,600)中加速器拿到的是動畫的比例值芋浮,估值器根據(jù)比例轉(zhuǎn)換成實際的值抱环。AnimatorUpdateListener監(jiān)聽器中拿到的實際數(shù)值,就是通過Evaluator轉(zhuǎn)換后的值。)

  • 看下面系統(tǒng)Evaluator代碼:
//設(shè)置取值區(qū)間時setIntValues(0,600)/setFloatValues(0,600),這是系統(tǒng)方法镇草,會自動為我們設(shè)置相應(yīng)的類型的Evaluator眶痰。

public class IntEvaluator implements TypeEvaluator<Integer> {
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
    
        //fraction是在插值器中處理后的進度,在這里以此轉(zhuǎn)換成實際值梯啤。
        int startInt = startValue;
        return (int)(startInt + fraction * (endValue - startInt));
    }
}
  • 開下面自定義Evaluator代碼:
public class PointEvaluator implements TypeEvaluator<Point> {
    @Override
    public Point evaluate(float fraction, Point startValue, Point endValue) {
        int radius = (int) (startValue.getRadius() + fraction*(endValue.getRadius() - startValue.getRadius()));
        return new Point(radius);
    }
}
public void doAnimation(){
        //ValueAnimator animatior = ValueAnimator.ofObject(new PointEvaluator(), new Point(20), new Point(80));
        //上下作用一樣竖伯,不可混用。
        ValueAnimator animatior = new ValueAnimator();
        animatior.setObjectValues(new Point(20), new Point(80));
        animatior.setEvaluator(new PointEvaluator());
        
        animatior.setDuration(2000);
        animatior.setInterpolator(new BounceInterpolator());
        animatior.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mPoint = (Point) animation.getAnimatedValue();
                invalidate();
            }
        });
        animatior.start();
    }

關(guān)于取值范圍

  • void setObjectValues(Object... values);
  • void setIntValues(int... values);
  • void setFloatValues(float... values);
animatior.setObjectValues(new Point(20), new Point(150),new Point(80), new Point(200), new Point(20), new Point(150));
animatior.setDuration(2000);

public class PointEvaluator implements TypeEvaluator<Point> {
    @Override
    public Point evaluate(float fraction, Point startValue, Point endValue) {
        int radius = (int) (startValue.getRadius() + fraction*(endValue.getRadius() - startValue.getRadius()));
        return new Point(radius);
    }
}

看上面的代碼可以發(fā)現(xiàn)因宇,setObjetValue可以有n個值黔夭。但是Evaluator估值器中只有startValue和endValue。

               26.698   evaluate: startPoint=20-endPoint=150-fraction=0.0
               ......
               26.979   evaluate: startPoint=20-endPoint=150-fraction=0.994
               
               26.995   evaluate: startPoint=150-endPoint=80-fraction=0.049999993
               27.245   evaluate: startPoint=150-endPoint=80-fraction=0.92499995
               27.262   evaluate: startPoint=150-endPoint=80-fraction=0.9844998
               
               27.278   evaluate: startPoint=80-endPoint=200-fraction=0.043999884
               ......
               27.546   evaluate: startPoint=80-endPoint=200-fraction=0.975
               
               27.562   evaluate: startPoint=200-endPoint=20-fraction=0.03449991
               ......
               27.828   evaluate: startPoint=200-endPoint=20-fraction=0.9689996
               
               27.847   evaluate: startPoint=20-endPoint=150-fraction=0.02499974
               ......
               28.112   evaluate: startPoint=20-endPoint=150-fraction=0.9595001
               
               28.129   evaluate: startPoint=150-endPoint=80-fraction=0.018999936
               ......
               28.179   evaluate: startPoint=150-endPoint=80-fraction=0.99399978

ke以發(fā)現(xiàn)羽嫡,設(shè)置取值范圍的時候本姥,有幾個參數(shù),就把setDuration(2000)的時間分為多少分杭棵,1&2/2&3 / 3&4...作為start/endValue婚惫。至于每份取得的時間比例,就看設(shè)置的插值器了魂爪。


tips

  • ArgbEvalutor 顏色估值器先舷。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市滓侍,隨后出現(xiàn)的幾起案子蒋川,更是在濱河造成了極大的恐慌,老刑警劉巖撩笆,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捺球,死亡現(xiàn)場離奇詭異,居然都是意外死亡夕冲,警方通過查閱死者的電腦和手機氮兵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來歹鱼,“玉大人泣栈,你說我怎么就攤上這事∶忠觯” “怎么了南片?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長庭敦。 經(jīng)常有香客問我疼进,道長,這世上最難降的妖魔是什么螺捐? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任颠悬,我火速辦了婚禮矮燎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赔癌。我一直安慰自己诞外,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布灾票。 她就那樣靜靜地躺著峡谊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪刊苍。 梳的紋絲不亂的頭發(fā)上既们,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機與錄音正什,去河邊找鬼啥纸。 笑死,一個胖子當(dāng)著我的面吹牛婴氮,可吹牛的內(nèi)容都是我干的斯棒。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼主经,長吁一口氣:“原來是場噩夢啊……” “哼荣暮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起罩驻,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤穗酥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后惠遏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體砾跃,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年爽哎,在試婚紗的時候發(fā)現(xiàn)自己被綠了蜓席。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡课锌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出祈秕,到底是詐尸還是另有隱情渺贤,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布请毛,位于F島的核電站志鞍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏方仿。R本人自食惡果不足惜固棚,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一统翩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧此洲,春花似錦厂汗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至汁汗,卻和暖如春衷畦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背知牌。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工祈争, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人角寸。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓菩混,卻偏偏與公主長得像,于是被迫代替她去往敵國和親袭厂。 傳聞我的和親對象是個殘疾皇子墨吓,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容