Android動畫基礎詳析 | 屬性動畫基礎及ValueAnimator

為什么要引入屬性動畫

  • 逐幀動畫主要是用來實現(xiàn)動畫的静袖,
    而補間動畫才能實現(xiàn)控件的漸入漸出、移動俊扭、旋轉和縮放效果队橙;
    屬性動畫是在Android 3.0時才引入的,之前是沒有的萨惑。

既然補間動畫和逐幀動畫已經(jīng)很全了捐康,為什么還要引入屬性動畫呢?

  • 假設:如何利用補間動畫來將一個控件的背景色在1分鐘內從綠色變?yōu)榧t色庸蔼?
    這個效果是沒辦法僅僅通過改變控件的漸入漸出解总、移動、旋轉和縮放來實現(xiàn)的姐仅,
    但卻可以通過屬性動畫完美地實現(xiàn)花枫。
    這就是要引入屬性動畫的第一個原因:
    屬性動畫是為了彌補視圖動畫的不足而設計的刻盐,
    能夠實現(xiàn)補間動畫無法實現(xiàn)的功能。

  • 補間動畫逐幀動畫統(tǒng)稱為視圖動畫乌昔,
    字面意思中可以看出隙疚,
    兩個動畫只能對派生自View類控件實例起作用壤追;

    屬性動畫磕道,
    名字中可看出它作用于控件屬性
    正因為屬性動畫能夠只針對控件某一個屬性來做動畫行冰,
    所以造就了它能單獨改變控件某一個屬性的溺蕉,比如顏色
    這就是屬性動畫能實現(xiàn)補間動畫無法實現(xiàn)的功能的最重要的原因悼做。

  • 視圖動畫僅能對指定的View實例控件做動畫疯特,
    屬性動畫是通過改變控件某一屬性值來做動畫的。

我們準備一個button和一個TextView肛走,
首先給TextView控件添加了單擊響應事件漓雅,
當單擊該TextView時,會彈出Toast提示朽色;
然后邻吞,
在單擊按鈕的時候,TextView控件開始向右下角移動葫男。
從結果中可以看出抱冷,
在移動前,單擊TextView控件是可以彈出Toast提示的梢褐;
而在移動后旺遮,單擊TextView控件則沒有響應,
相反盈咳,單擊TextView控件原來所在的區(qū)域會彈出Toast提示耿眉。
這就說明補間動畫雖然能對控件做動畫,
但是并沒有改變控件內部的屬性值鱼响。

視圖動畫與屬性動畫的區(qū)別

  • 1.操作對象

    • 視圖動畫只能操作視圖對象(各種組件鸣剪、各種View、ViewGroup)热押;

    • 屬性動畫可以操作任意對象(除了View西傀,還可以是基本類型數(shù)據(jù)等);

      • 動畫系統(tǒng)本質:給定一個初始值和一個終止值桶癣,
        令對象從初始值到終止值做一個平滑的變化(變化過程可以變速拥褂、勻速、不規(guī)則速度)
    1. 屬性的改變
    • 視圖動畫沒有對屬性做真正的改變牙寞,只是做出動畫效果而已饺鹃;
      (位移動畫后View的響應區(qū)沒有改變莫秆;縮放動畫結束后獲取View的長寬其值亦沒有改變)
    • 屬性動畫能夠做真正的屬性改變;
      • 視圖動畫實現(xiàn)的效果悔详,屬性動畫都能實現(xiàn)镊屎;

從直觀上來看,視圖動畫與屬性動畫有如下三點不同茄螃。
(1)引入時間不同:View Animation是在API Level 1時引入的缝驳;而Property Animation是在API Level 11時引入的,即從Android 3.0才開始有與Property Animation相關的API归苍。
(2)所在包名不同:View Animation API在android.view.animation 包中用狱,而Property Animation API在android.animation包中。
(3)動畫類的命名不同:View Animation中的動畫類命名都是XXXXAnimation拼弃,而Property Animation中的動畫類命名都是XXXXAnimator夏伊。


動畫屬性

  • 1 時長

  • 2 時間插值器

  • 3 重復次數(shù)以及重復模式

  • 4 動畫集

  • 5 延遲

    • 屬性動畫干的事情,就是在一段時間內讓屬性值不斷地做變化吻氧;
      (變化過程可以變速溺忧、勻速、不規(guī)則速度)盯孙,
      一系列的屬性改變即成就了一個動畫鲁森;
  • 屬性動畫相關的類,
    都被定義在了android.animation包當中镀梭,
    包中有一個抽象類Animator刀森,
    它包含了以上提到的五個屬性的相關方法;

  • 動畫對象都是可悲開始报账、可被暫停研底、可被監(jiān)聽的;

  • Animator的子類

    • ValueAnimator 控制值的變化透罢;
      屬性動畫干的事情榜晦,就是在一段時間內讓屬性值不斷地做變化;
      ValueAnimator 就是令這個屬性值不斷地做變化的驅動羽圃;


ValueAnimator

在上篇博客Android動畫基礎詳析 | 概述乾胶、逐幀動畫、視圖動畫(附諸多實際運行效果動圖)的基礎上我們新建一個property包和一個PropertyActivity:

activity_property.xml:

<?xml version="1.0" encoding="utf-8"?>
<RealativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".property.PropertyActivity">

    <Button
        android:id="@+id/btnValueAnimator"
        android:text="Go"
        android:onClick="onClick"
        android:layout_width = "match_parent"
        android:layout_height= "wrap_content"/> 

</RealativeLayout>

PropertyActivity.java:

public class PropertyActivity extends AppCompatActivity {

    private static final String TAG = "PropertyActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_property);
    }

    public void onClick(View view){
        switch (view.getId()){
            case R.id.btnValueAnimator:
                ValueAnimator valueAnimator = ValueAnimator.ofInt(0,100);//ValueAnimator的正態(tài)方法ofInt朽寞,驅動整型數(shù)值
                valueAnimator.setDuration(100);//設置時長
                //設置屬性刷新監(jiān)聽器
                valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        //通過animation對象可以獲取諸多動畫相關屬性

                        //獲取當前的動畫變化完成度识窿,范圍 0.0 - 1.0,0.0表示剛開始脑融, 1.0表示完成
                        float animatedFracion = animation.getAnimatedFraction();
                        //獲取當前狀態(tài)基于正態(tài)方法的始末參數(shù)間的插值喻频,強制轉換的類型就看正態(tài)方法的數(shù)據(jù)類型;
                        int animatedValue = (int)animation.getAnimatedValue();
                        //打印這兩個參數(shù)肘迎,其中%.3f即保留小數(shù)點后三位
                        Log.d(TAG, "onAnimationUpdate: "
                                + String.format("%.3f %d", animatedFracion,animatedValue));
                    }
                });
                valueAnimator.start();//開始動畫
                break;
        }
    }
}

運行代碼:

第一列數(shù)據(jù)是動畫變化完成度甥温,第二列數(shù)據(jù)是插值锻煌,
我們可以看到打印出來的值并不是線性的,???
因為ValueAnimator默認的插值器不是勻速的姻蚓;???
下面給ValueAnimator設置插值器即可:

...
valueAnimator.setDuration(100);//設置時長
                valueAnimator.setInterpolator(new LinearInterpolator());//設置插值器
                //設置屬性刷新監(jiān)聽器
...


ValueAnimator的簡單使用案例

  • ValueAnimator.ofFloat(0f宋梧,400f,50f狰挡,300f)
    構造了一個比較復雜的動畫漸變捂龄,
    值從0變到400,再回到50圆兵,最后變成300跺讯,
    通過getAnimatedValue()函數(shù)來獲取當前運動點的值,
    在得到當前運動點的值以后殉农,
    通過layout()函數(shù)將TextView移動到指定位置即可
  • ValueAnimator只負責對指定值區(qū)間進行動畫運算;
    我們需要對運算過程進行監(jiān)聽局荚,然后自己對控件執(zhí)行動畫操作超凳。

  • ofInt()與ofFloat()的唯一區(qū)別就是傳入的數(shù)值類型不一樣,ofInt()函數(shù)需要傳入Integer類型的參數(shù)耀态,而ofFloat()函數(shù)則需要傳入Float類型的參數(shù)轮傍。

    它們的參數(shù)類型都是可變長參數(shù),所以我們可以傳入任何數(shù)量的值首装;
    傳進去的值列表就表示動畫時的變化范圍创夜,
    比如ofInt(2,90仙逻,45)就表示從數(shù)字2變化到數(shù)字90再變化到數(shù)字45驰吓,
    所以我們傳進去的數(shù)字越多,
    動畫變化就越復雜系奉。


  • 為什么通過getAnimatedValue()函數(shù)來獲取當前valueAnimator產(chǎn)生的值的時候檬贰,需要轉換成Integer/Float類型?

getAnimatedValue()函數(shù)的聲明Object getAnimatedValue();
它返回的是Object原始類型缺亮,
那我們怎么知道要將它轉換成什么類型呢翁涤?

注意,
如果我們在設定動畫初始值時使用的是ofFloat()函數(shù)萌踱,
則每個值的類型必定是Float類型葵礼,
我們獲取到的類型也必然是Float類型。

同樣并鸵,如果我們使用ofInt()函數(shù)設定動畫初始值鸳粉,
那么通過getAnimatedValue()函數(shù)獲取到的值
就應該轉換為Integer類型。



常用函數(shù)匯總
  • setRepeatCount(int value)函數(shù)用于設置動畫循環(huán)次數(shù)能真,
    設置為0表示不循環(huán)赁严,
    設置為ValueAnimation.INFINITE表示無限循環(huán)扰柠。

  • cancel()函數(shù)用于取消動畫。

  • setRepeatMode(int value)函數(shù)用于設置循環(huán)模式疼约,
    當取值為ValueAnimation.RESTART時卤档,表示正序重新開始;
    當取值為ValueAnimation.REVERSE時程剥,表示倒序重新開始劝枣。

  • 注意:重復次數(shù)為INFINITE(無限循環(huán))的動畫,
    當Activity結束的時候织鲸,必須調用cancel()函數(shù)取消動畫舔腾,
    否則動畫將無限循環(huán),從而導致View無法釋放搂擦,
    進一步導致整個Activity無法釋放稳诚,最終引起內存泄漏。

監(jiān)聽器
  • animator.addUpdateListener瀑踢,用于監(jiān)聽動畫過程中值的實時變化扳还。

    其實在ValueAnimator中,共有兩個監(jiān)聽器:
  • 當動畫開始時橱夭,會通過onAnimationStart()函數(shù)返回氨距;
    在每一次重復時,都會調用一次onAnimationRepeat()函數(shù)棘劣;
    在調用cancel()函數(shù)取消動畫時俏让,會通過onAnimationCancel()函數(shù)返回;
    在動畫終止時茬暇,會調用onAnimationEnd()函數(shù)通知用戶首昔;
移除監(jiān)聽器
  • removeListener(AnimatorListener listener)函數(shù)
    用于在Animator中移除指定的監(jiān)聽器;

  • removeAllListeners()函數(shù)
    用于移除Animator中所有的監(jiān)聽器而钞。

其他函數(shù)
  • setStartDelay(long startDelay)函數(shù)非常容易理解沙廉,就是設置延時多久后動畫開始。
  • clone()函數(shù)就是復制出來一個完全一樣的新的ValueAnimator實例臼节,
    對原來的ValueAnimator是怎么處理的撬陵,
    在這個新的實例中也采用相同的處理方式;

至此网缝,補充一個實戰(zhàn):
自定義View實戰(zhàn) | 彈跳的loading效果
一個主要是由ValueAnimator實現(xiàn)的自定義View










?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末草添,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子扼仲,更是在濱河造成了極大的恐慌远寸,老刑警劉巖抄淑,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異驰后,居然都是意外死亡肆资,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門灶芝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來郑原,“玉大人,你說我怎么就攤上這事夜涕》咐纾” “怎么了?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵女器,是天一觀的道長酸役。 經(jīng)常有香客問我,道長晓避,這世上最難降的妖魔是什么簇捍? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮俏拱,結果婚禮上,老公的妹妹穿的比我還像新娘吼句。我一直安慰自己锅必,他們只是感情好,可當我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布惕艳。 她就那樣靜靜地躺著搞隐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪远搪。 梳的紋絲不亂的頭發(fā)上劣纲,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天,我揣著相機與錄音谁鳍,去河邊找鬼癞季。 笑死,一個胖子當著我的面吹牛倘潜,可吹牛的內容都是我干的绷柒。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼涮因,長吁一口氣:“原來是場噩夢啊……” “哼废睦!你這毒婦竟也來了?” 一聲冷哼從身側響起养泡,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤嗜湃,失蹤者是張志新(化名)和其女友劉穎奈应,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體购披,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡杖挣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了今瀑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片程梦。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖橘荠,靈堂內的尸體忽然破棺而出屿附,到底是詐尸還是另有隱情,我是刑警寧澤哥童,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布挺份,位于F島的核電站,受9級特大地震影響贮懈,放射性物質發(fā)生泄漏匀泊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一朵你、第九天 我趴在偏房一處隱蔽的房頂上張望各聘。 院中可真熱鬧,春花似錦抡医、人聲如沸躲因。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽大脉。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哭懈。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留秤标,地道東北人。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓安疗,卻偏偏與公主長得像抛杨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子荐类,可洞房花燭夜當晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內容

  • 【Android 動畫】 動畫分類補間動畫(Tween動畫)幀動畫(Frame 動畫)屬性動畫(Property ...
    Rtia閱讀 6,182評論 1 38
  • 1 背景 不能只分析源碼呀怖现,分析的同時也要整理歸納基礎知識,剛好有人微博私信讓全面說說Android的動畫,所以今...
    未聞椛洺閱讀 2,719評論 0 10
  • 參考于:http://blog.csdn.net/guolin_blog/article/details/4353...
    墨染書閱讀 2,929評論 0 2
  • 動畫基礎概念 動畫分類 Android 中動畫分為兩種屈嗤,一種是 Tween 動畫潘拨、還有一種是 Frame 動畫。 ...
    Rtia閱讀 1,236評論 0 6
  • 一早醒來 久違的太陽穿過窗簾 連同空氣中 多了很多跳躍的音符 微風拂過 知了聲細細密密 飄在鳥兒的晨鳴里...
    會飛的果子閱讀 388評論 4 8