面試現(xiàn)場,數(shù)十人競爭一個崗位,程序員霸氣寫下動畫特效奪得第一

大家好,我們學(xué)習(xí)了Android屬性動畫的基本用法,當(dāng)然也是最常用的一些用法,這些用法足以覆蓋我們平時大多情況下的動畫需求了。但是,屬性動畫對補間動畫進行了很大幅度的改進,之前補間動畫可以做到的屬性動畫也能做到,補間動畫做不到的現(xiàn)在屬性動畫也可以做到了。因此,今天我們就來學(xué)習(xí)一下屬性動畫的高級用法,看看如何實現(xiàn)一些補間動畫所無法實現(xiàn)的功能。

先來看看效果如下圖所示:

  ValueAnimator的高級用法

  在上篇文章中介紹補間動畫缺點的時候有提到過,補間動畫是只能對View對象進行動畫操作的。而屬性動畫就不再受這個限制,它可以對任意對象進行動畫操作。那么大家應(yīng)該還記得在上篇文章當(dāng)中我舉的一個例子,比如說我們有一個自定義的View,在這個View當(dāng)中有一個Point對象用于管理坐標(biāo),然后在onDraw()方法當(dāng)中就是根據(jù)這個Point對象的坐標(biāo)值來進行繪制的。也就是說,如果我們可以對Point對象進行動畫操作,那么整個自定義View的動畫效果就有了。OK,下面我們就來學(xué)習(xí)一下如何實現(xiàn)這樣的效果。

  在開始動手之前,我們還需要掌握另外一個知識點,就是TypeEvaluator的用法??赡茉诖蠖鄶?shù)情況下我們使用屬性動畫的時候都不會用到TypeEvaluator,但是大家還是應(yīng)該了解一下它的用法,以防止當(dāng)我們遇到一些解決不掉的問題時能夠想起來還有這樣的一種解決方案。

  那么TypeEvaluator的作用到底是什么呢?簡單來說,就是告訴動畫系統(tǒng)如何從初始值過度到結(jié)束值。我們在上一篇文章中學(xué)到的ValueAnimator.ofFloat()方法就是實現(xiàn)了初始值與結(jié)束值之間的平滑過度,那么這個平滑過度是怎么做到的呢?其實就是系統(tǒng)內(nèi)置了一個FloatEvaluator,它通過計算告知動畫系統(tǒng)如何從初始值過度到結(jié)束值,我們來看一下FloatEvaluator的代碼實現(xiàn):


  可以看到,F(xiàn)loatEvaluator實現(xiàn)了TypeEvaluator接口,然后重寫evaluate()方法。evaluate()方法當(dāng)中傳入了三個參數(shù),第一個參數(shù)fraction非常重要,這個參數(shù)用于表示動畫的完成度的,我們應(yīng)該根據(jù)它來計算當(dāng)前動畫的值應(yīng)該是多少,第二第三個參數(shù)分別表示動畫的初始值和結(jié)束值。那么上述代碼的邏輯就比較清晰了,用結(jié)束值減去初始值,算出它們之間的差值,然后乘以fraction這個系數(shù),再加上初始值,那么就得到當(dāng)前動畫的值了。

  好的,那FloatEvaluator是系統(tǒng)內(nèi)置好的功能,并不需要我們自己去編寫,但介紹它的實現(xiàn)方法是要為我們后面的功能鋪路的。前面我們使用過了ValueAnimator的ofFloat()和ofInt()方法,分別用于對浮點型和整型的數(shù)據(jù)進行動畫操作的,但實際上ValueAnimator中還有一個ofObject()方法,是用于對任意對象進行動畫操作的。但是相比于浮點型或整型數(shù)據(jù),對象的動畫操作明顯要更復(fù)雜一些,因為系統(tǒng)將完全無法知道如何從初始對象過度到結(jié)束對象,因此這個時候我們就需要實現(xiàn)一個自己的TypeEvaluator來告知系統(tǒng)如何進行過度。

  下面來先定義一個Point類,如下所示:


  Point類非常簡單,只有x和y兩個變量用于記錄坐標(biāo)的位置,并提供了構(gòu)造方法來設(shè)置坐標(biāo),以及get方法來獲取坐標(biāo)。接下來定義PointEvaluator,如下所示:


  可以看到,PointEvaluator同樣實現(xiàn)了TypeEvaluator接口并重寫了evaluate()方法。其實evaluate()方法中的邏輯還是非常簡單的,先是將startValue和endValue強轉(zhuǎn)成Point對象,然后同樣根據(jù)fraction來計算當(dāng)前動畫的x和y的值,最后組裝到一個新的Point對象當(dāng)中并返回。

  這樣我們就將PointEvaluator編寫完成了,接下來我們就可以非常輕松地對Point對象進行動畫操作了,比如說我們有兩個Point對象,現(xiàn)在需要將Point1通過動畫平滑過度到Point2,就可以這樣寫:


  代碼很簡單,這里我們先是new出了兩個Point對象,并在構(gòu)造函數(shù)中分別設(shè)置了它們的坐標(biāo)點。然后調(diào)用ValueAnimator的ofObject()方法來構(gòu)建ValueAnimator的實例,這里需要注意的是,ofObject()方法要求多傳入一個TypeEvaluator參數(shù),這里我們只需要傳入剛才定義好的PointEvaluator的實例就可以了。

  好的,這就是自定義TypeEvaluator的全部用法,掌握了這些知識之后,我們就可以來嘗試一下如何通過對Point對象進行動畫操作,從而實現(xiàn)整個自定義View的動畫效果。

  新建一個MyAnimView繼承自View,代碼如下所示:


  基本上還是很簡單的,總共也沒幾行代碼。首先在自定義View的構(gòu)造方法當(dāng)中初始化了一個Paint對象作為畫筆,并將畫筆顏色設(shè)置為藍色,接著在onDraw()方法當(dāng)中進行繪制。這里我們繪制的邏輯是由currentPoint這個對象控制的,如果currentPoint對象不等于空,那么就調(diào)用drawCircle()方法在currentPoint的坐標(biāo)位置畫出一個半徑為50的圓,如果currentPoint對象是空,那么就調(diào)用startAnimation()方法來啟動動畫。

  那么我們來觀察一下startAnimation()方法中的代碼,其實大家應(yīng)該很熟悉了,就是對Point對象進行了一個動畫操作而已。這里我們定義了一個startPoint和一個endPoint,坐標(biāo)分別是View的左上角和右下角,并將動畫的時長設(shè)為5秒。然后有一點需要大家注意的,就是我們通過監(jiān)聽器對動畫的過程進行了監(jiān)聽,每當(dāng)Point值有改變的時候都會回調(diào)onAnimationUpdate()方法。在這個方法當(dāng)中,我們對currentPoint對象進行了重新賦值,并調(diào)用了invalidate()方法,這樣的話onDraw()方法就會重新調(diào)用,并且由于currentPoint對象的坐標(biāo)已經(jīng)改變了,那么繪制的位置也會改變,于是一個平移的動畫效果也就實現(xiàn)了。

  下面我們只需要在布局文件當(dāng)中引入這個自定義控件:


  分享之前我還是要推薦下我自己建的Android學(xué)習(xí)群:654759632,史上第一個Android5000人群,都是學(xué)Android開發(fā)的,如果你正在學(xué)習(xí)Android,小編歡迎你加入,今天分享的這個案例已經(jīng)上傳到群文件,大家都是Android黨,不定期分享干貨(只有Android開發(fā)相關(guān)的),包括我自己整理的一份2017最新的Android資料和零基礎(chǔ)入門教程,歡迎初學(xué)和進階中的小伙伴。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容