Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android--應用開發之所有動畫使用詳解

Android--應用開發之所有動畫使用詳解

日期:2017/2/23 15:32:15      編輯:關於Android編程

1 背景

不能只分析源碼呀,分析的同時也要整理歸納基礎知識,剛好有人微博私信讓全面說說Android的動畫,所以今天來一發Android應用的各種Animation大集合。英文厲害的請直接移步參考Android Developer。

Android系統提供了很多豐富的API去實現UI的2D與3D動畫,最主要的劃分可以分為如下幾類:

  • View Animation:視圖動畫在古老的Android版本系統中就已經提供了,只能被用來設置View的動畫。

  • Drawable Animation:這種動畫(也叫Frame動畫、幀動畫)其實可以劃分到視圖動畫的類別,專門用來一個一個的顯示Drawable的resources,就像放幻燈片一樣。

  • Property Animation:屬性動畫只對Android 3.0(API 11)以上版本的Android系統才有效,這種動畫可以設置給任何Object,包括那些還沒有渲染到屏幕上的對象。這種動畫是可擴展的,可以讓你自定義任何類型和屬性的動畫。

    可以看見,當前應用程序開發涉及的主要動畫也就這三大類,我們接下來以類別為基礎來慢慢展開說明。

     

    2 View Animation(視圖動畫)使用詳解

    2-1 視圖動畫概述

    視圖動畫,也叫Tween(補間)動畫可以在一個視圖容器內執行一系列簡單變換(位置、大小、旋轉、透明度)。譬如,如果你有一個TextView對象,您可以移動、旋轉、縮放、透明度設置其文本,當然,如果它有一個背景圖像,背景圖像會隨著文本變化。

    補間動畫通過XML或Android代碼定義,建議使用XML文件定義,因為它更具可讀性、可重用性。

    如下是視圖動畫相關的類繼承關系:

    這裡寫圖片描述

    java類名 xml關鍵宗喎?/kf/yidong/wp/" target="_blank" class="keylink">WPC90aD4NCgk8dGg+DQoJCcPoyvbQxc+iPC90aD4NCgk8L3RyPg0KPC90aGVhZD4NCjx0Ym9keT4NCgk8dHI+DQoJPHRkPkFscGhhQW5pbWF0aW9uPC90ZD4NCgk8dGQ+PGNvZGU+PGFscGhhPjwvYWxwaGE+PC9jb2RlPrfF1sPU2nJlcy9hbmltL8S/wrzPwjwvdGQ+DQoJPHRkPr2lseTNuMP3tsi2r7ut0Ke5+zwvdGQ+DQoJPC90cj4NCgk8dHI+DQoJPHRkPlJvdGF0ZUFuaW1hdGlvbjwvdGQ+DQoJPHRkPjxjb2RlPjxyb3RhdGU+PC9yb3RhdGU+PC9jb2RlPrfF1sPU2nJlcy9hbmltL8S/wrzPwjwvdGQ+DQoJPHRkPrutw+bXqtLG0P3Xqravu63Qp7n7PC90ZD4NCgk8L3RyPg0KCTx0cj4NCgk8dGQ+U2NhbGVBbmltYXRpb248L3RkPg0KCTx0ZD48Y29kZT48c2NhbGU+PC9zY2FsZT48L2NvZGU+t8XWw9TacmVzL2FuaW0vxL/CvM/CPC90ZD4NCgk8dGQ+vaWx5LPftOfJ7Mv1tq+7rdCnufs8L3RkPg0KCTwvdHI+DQoJPHRyPg0KCTx0ZD5UcmFuc2xhdGVBbmltYXRpb248L3RkPg0KCTx0ZD48Y29kZT48dHJhbnNsYXRlPjwvdHJhbnNsYXRlPjwvY29kZT63xdbD1NpyZXMvYW5pbS/Ev8K8z8I8L3RkPg0KCTx0ZD67rcPm16q7u8671sPSxravtq+7rdCnufs8L3RkPg0KCTwvdHI+DQoJPHRyPg0KCTx0ZD5BbmltYXRpb25TZXQ8L3RkPg0KCTx0ZD48Y29kZT48c2V0Pjwvc2V0PjwvY29kZT63xdbD1NpyZXMvYW5pbS/Ev8K8z8I8L3RkPg0KCTx0ZD7Su7j2s9bT0Mbky/y2r7ut1KrL2GFscGhhoaJzY2FsZaGidHJhbnNsYXRloaJyb3RhdGW78tXfxuTL/HNldNSqy9i1xMjdxvc8L3RkPg0KCTwvdHI+DQo8L3Rib2R5Pg0KPC90YWJsZT4NCjxwPs2ouf3Jz828us3Jz7Htv8nS1Naxudu1xL+0s/bAtLK5vOS2r7uttcS52M+1vLDW1sDgwcuwyaOsvdPPwsC0ztLDx77Nz+rPuNK7uPbSu7j2tcS96cnc0rvPwrj31tayubzktq+7raGjPC9wPg0KPGgzIGlkPQ=="2-2-視圖動畫詳細說明">2-2 視圖動畫詳細說明

    可以看出來Animation抽象類是所有補間動畫類的基類,所以基類會提供一些通用的動畫屬性方法,如下我們就來詳細看看這些屬性,關於這些屬性詳細官方解釋翻牆點擊我或者翻牆點擊我。

    2-2-1 Animation屬性詳解

    xml屬性 java方法 解釋 android:detachWallpaper setDetachWallpaper(boolean) 是否在壁紙上運行 android:duration setDuration(long) 動畫持續時間,毫秒為單位 android:fillAfter setFillAfter(boolean) 控件動畫結束時是否保持動畫最後的狀態 android:fillBefore setFillBefore(boolean) 控件動畫結束時是否還原到開始動畫前的狀態 android:fillEnabled setFillEnabled(boolean) 與android:fillBefore效果相同 android:interpolator setInterpolator(Interpolator) 設定插值器(指定的動畫效果,譬如回彈等) android:repeatCount setRepeatCount(int) 重復次數 android:repeatMode setRepeatMode(int) 重復類型有兩個值,reverse表示倒序回放,restart表示從頭播放 android:startOffset setStartOffset(long) 調用start函數之後等待開始運行的時間,單位為毫秒 android:zAdjustment setZAdjustment(int) 表示被設置動畫的內容運行時在Z軸上的位置(top/bottom/normal),默認為normal


    也就是說,無論我們補間動畫的哪一種都已經具備了這種屬性,也都可以設置使用這些屬性中的一個或多個。

    那接下來我們就看看每種補間動畫特有的一些屬性說明吧。

    2-2-2 Alpha屬性詳解

    xml屬性 java方法 解釋 android:fromAlpha AlphaAnimation(float fromAlpha, …) 動畫開始的透明度(0.0到1.0,0.0是全透明,1.0是不透明) android:toAlpha AlphaAnimation(…, float toAlpha) 動畫結束的透明度,同上

    2-2-3 Rotate屬性詳解

    xml屬性 java方法 解釋 android:fromDegrees RotateAnimation(float fromDegrees, …) 旋轉開始角度,正代表順時針度數,負代表逆時針度數 android:toDegrees RotateAnimation(…, float toDegrees, …) 旋轉結束角度,正代表順時針度數,負代表逆時針度數 android:pivotX RotateAnimation(…, float pivotX, …) 縮放起點X坐標(數值、百分數、百分數p,譬如50表示以當前View左上角坐標加50px為初始點、50%表示以當前View的左上角加上當前View寬高的50%做為初始點、50%p表示以當前View的左上角加上父控件寬高的50%做為初始點) android:pivotY RotateAnimation(…, float pivotY) 縮放起點Y坐標,同上規律

    2-2-4 Scale屬性詳解

    xml屬性 java方法 解釋 android:fromXScale ScaleAnimation(float fromX, …) 初始X軸縮放比例,1.0表示無變化 android:toXScale ScaleAnimation(…, float toX, …) 結束X軸縮放比例 android:fromYScale ScaleAnimation(…, float fromY, …) 初始Y軸縮放比例 android:toYScale ScaleAnimation(…, float toY, …) 結束Y軸縮放比例 android:pivotX ScaleAnimation(…, float pivotX, …) 縮放起點X軸坐標(數值、百分數、百分數p,譬如50表示以當前View左上角坐標加50px為初始點、50%表示以當前View的左上角加上當前View寬高的50%做為初始點、50%p表示以當前View的左上角加上父控件寬高的50%做為初始點) android:pivotY ScaleAnimation(…, float pivotY) 縮放起點Y軸坐標,同上規律

    2-2-5 Translate屬性詳解

    xml屬性 java方法 解釋 android:fromXDelta TranslateAnimation(float fromXDelta, …) 起始點X軸坐標(數值、百分數、百分數p,譬如50表示以當前View左上角坐標加50px為初始點、50%表示以當前View的左上角加上當前View寬高的50%做為初始點、50%p表示以當前View的左上角加上父控件寬高的50%做為初始點) android:fromYDelta TranslateAnimation(…, float fromYDelta, …) 起始點Y軸從標,同上規律 android:toXDelta TranslateAnimation(…, float toXDelta, …) 結束點X軸坐標,同上規律 android:toYDelta TranslateAnimation(…, float toYDelta) 結束點Y軸坐標,同上規律

    2-2-6 AnimationSet詳解

    AnimationSet繼承自Animation,是上面四種的組合容器管理類,沒有自己特有的屬性,他的屬性繼承自Animation,所以特別注意,當我們對set標簽使用Animation的屬性時會對該標簽下的所有子控件都產生影響。

    2-3 視圖動畫使用方法

    通過上面對於動畫的屬性介紹之後我們來看看在Android中這些動畫如何使用(PS:這裡直接演示xml方式,至於java方式太簡單了就不說了),如下:

    
    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@[package:]anim/interpolator_resource"
        android:shareInterpolator=["true" | "false"] >
        <alpha
            android:fromAlpha="float"
            android:toAlpha="float" />
        <scale
            android:fromXScale="float"
            android:toXScale="float"
            android:fromYScale="float"
            android:toYScale="float"
            android:pivotX="float"
            android:pivotY="float" />
        <translate
            android:fromXDelta="float"
            android:toXDelta="float"
            android:fromYDelta="float"
            android:toYDelta="float" />
        <rotate
            android:fromDegrees="float"
            android:toDegrees="float"
            android:pivotX="float"
            android:pivotY="float" />
        <set>
            ...
        set>
    set>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    ImageView spaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);
    Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
    spaceshipImage.startAnimation(hyperspaceJumpAnimation);
    • 1
    • 2
    • 3

    上面就是一個標准的使用我們定義的補間動畫的模板。至於補間動畫的使用,Animation還有如下一些比較實用的方法介紹:

    Animation類的方法 解釋 reset() 重置Animation的初始化 cancel() 取消Animation動畫 start() 開始Animation動畫 setAnimationListener(AnimationListener listener) 給當前Animation設置動畫監聽 hasStarted() 判斷當前Animation是否開始 hasEnded() 判斷當前Animation是否結束


    既然補間動畫只能給View使用,那就來看看View中和動畫相關的幾個常用方法吧,如下:

    View類的常用動畫操作方法 解釋 startAnimation(Animation animation) 對當前View開始設置的Animation動畫 clearAnimation() 取消當View在執行的Animation動畫

    到此整個Android的補間動畫常用詳細屬性及方法全部介紹完畢,如有特殊的屬性需求可以訪問Android Developer查閱即可。如下我們就來個綜合大演練。

    2-4 視圖動畫注意事項

    關於視圖動畫(補間動畫)的例子我就不介紹了,網上簡直多的都泛濫了。只是強調在使用補間動畫時注意如下一點即可:

    特別特別注意:補間動畫執行之後並未改變View的真實布局屬性值。切記這一點,譬如我們在Activity中有一個Button在屏幕上方,我們設置了平移動畫移動到屏幕下方然後保持動畫最後執行狀態呆在屏幕下方,這時如果點擊屏幕下方動畫執行之後的Button是沒有任何反應的,而點擊原來屏幕上方沒有Button的地方卻響應的是點擊Button的事件。

    2-5 視圖動畫Interpolator插值器詳解

    2-5-1 插值器簡介

    介紹補間動畫插值器之前我們先來看一幅圖,如下:

    這裡寫圖片描述

    可以看見其實各種插值器都是實現了Interpolator接口而已,同時可以看見系統提供了許多已經實現OK的插值器,具體如下:

    java類 xml id值 描述 AccelerateDecelerateInterpolator @android:anim/accelerate_decelerate_interpolator 動畫始末速率較慢,中間加速 AccelerateInterpolator @android:anim/accelerate_interpolator 動畫開始速率較慢,之後慢慢加速 AnticipateInterpolator @android:anim/anticipate_interpolator 開始的時候從後向前甩 AnticipateOvershootInterpolator @android:anim/anticipate_overshoot_interpolator 類似上面AnticipateInterpolator BounceInterpolator @android:anim/bounce_interpolator 動畫結束時彈起 CycleInterpolator @android:anim/cycle_interpolator 循環播放速率改變為正弦曲線 DecelerateInterpolator @android:anim/decelerate_interpolator 動畫開始快然後慢 LinearInterpolator @android:anim/linear_interpolator 動畫勻速改變 OvershootInterpolator @android:anim/overshoot_interpolator 向前彈出一定值之後回到原來位置 PathInterpolator   新增,定義路徑坐標後按照路徑坐標來跑。

    如上就是系統提供的一些插值器,下面我們來看看怎麼使用他們。

    2-5-2 插值器使用方法

    插值器的使用比較簡答,如下:

    <set android:interpolator="@android:anim/accelerate_interpolator">
        ...
    set>
    • 1
    • 2
    • 3

    2-5-3 插值器的自定義

    有時候你會發現系統提供的插值器不夠用,可能就像View一樣需要自定義。所以接下來我們來看看插值器的自定義,關於插值器的自定義分為兩種實現方式,xml自定義實現(其實就是對現有的插值器的一些屬性修改)或者java代碼實現方式。如下我們來說說。

    先看看XML自定義插值器的步驟:

    • 在res/anim/目錄下創建filename.xml文件。
    • 修改你准備自定義的插值器如下:
      
      <InterpolatorName xmlns:android="http://schemas.android.com/apk/res/android"
          android:attribute_name="value"
          />
      • 1
      • 2
      • 3
      • 4
      • 在你的補間動畫文件中引用該文件即可。

        可以看見上面第二步修改的是現有插值器的一些屬性,但是有些插值器卻不具備修改屬性,具體如下:

        無可自定義的attribute。

        android:factor 浮點值,加速速率(默認值為1)。

        android:tension 浮點值,起始點後拉的張力數(默認值為2)。

        android:tension 浮點值,起始點後拉的張力數(默認值為2)。
        android:extraTension 浮點值,拉力的倍數(默認值為1.5)。

        無可自定義的attribute。

        android:cycles 整形,循環的個數(默認為1)。

        android:factor 浮點值,減速的速率(默認為1)。

        無可自定義的attribute。

        android:tension 浮點值,超出終點後的張力(默認為2)。

        再來看看Java自定義插值器的(Java自定義插值器其實是xml自定義的升級,也就是說如果我們修改xml的屬性還不能滿足需求,那就可以選擇通過Java來實現)方式。

        可以看見上面所有的Interpolator都實現了Interpolator接口,而Interpolator接口又繼承自TimeInterpolator,TimeInterpolator接口定義了一個float getInterpolation(float input);方法,這個方法是由系統調用的,其中的參數input代表動畫的時間,在0和1之間,也就是開始和結束之間。

        如下就是一個動畫始末速率較慢、中間加速的AccelerateDecelerateInterpolator插值器:

        public class AccelerateDecelerateInterpolator extends BaseInterpolator
                implements NativeInterpolatorFactory {
            ......
            public float getInterpolation(float input) {
                return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
            }
            ......
        }
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8

        到此整個補間動畫與補間動畫的插值器都分析完畢了,接下來看下別的動畫。

        【工匠若水http://blog.csdn.net/yanbober轉載請注明出處。點我開始Android技術交流】

        3 Drawable Animation(Drawable動畫)使用詳解

        3-1 Drawable動畫概述

        Drawable動畫其實就是Frame動畫(幀動畫),它允許你實現像播放幻燈片一樣的效果,這種動畫的實質其實是Drawable,所以這種動畫的XML定義方式文件一般放在res/drawable/目錄下。具體關於幀動畫的xml使用方式翻牆點擊我查看,java方式翻牆點擊我查看。

        如下圖就是幀動畫的源碼文件:

        這裡寫圖片描述

        可以看見實際的真實父類就是Drawable。

        3-2 Drawable動畫詳細說明

        我們依舊可以使用xml或者java方式實現幀動畫。但是依舊推薦使用xml,具體如下:

        必須是根節點,包含一個或者多個元素,屬性有:

        • android:oneshottrue代表只執行一次,false循環執行。
        • 類似一幀的動畫資源。

          animation-list的子項,包含屬性如下:

          • android:drawable一個frame的Drawable資源。
          • android:duration一個frame顯示多長時間。

            3-3 Drawable動畫實例演示

            關於幀動畫相對來說比較簡單,這裡給出一個常規使用框架,如下:

            
            
            <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
                android:oneshot=["true" | "false"] >
                <item
                    android:drawable="@[package:]drawable/drawable_resource_name"
                    android:duration="integer" />
            animation-list>
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
            rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
            
            rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
            rocketAnimation.start();
            • 1
            • 2
            • 3
            • 4
            • 5

            特別注意,AnimationDrawable的start()方法不能在Activity的onCreate方法中調運,因為AnimationDrawable還未完全附著到window上,所以最好的調運時機是onWindowFocusChanged()方法中。

            至此幀動畫也就說明完成了。讓我們接下來進入Android更牛叉的動畫類型。

            【工匠若水http://blog.csdn.net/yanbober轉載請注明出處。點我開始Android技術交流】

            4 Property Animation(屬性動畫)使用詳解

            在使用屬性動畫之前先來看幾個常用的View屬性成員:

            • translationX,translationY:控制View的位置,值是相對於View容器左上角坐標的偏移。
            • rotationX,rotationY:控制相對於軸心旋轉。
            • x,y:控制View在容器中的位置,即左上角坐標加上translationX和translationY的值。
            • alpha:控制View對象的alpha透明度值。

              這幾個常用的屬性相信大家都很熟悉,接下來的屬性動畫我們就從這裡展開。

              4-1 屬性動畫概述

              Android 3.0以後引入了屬性動畫,屬性動畫可以輕而易舉的實現許多View動畫做不到的事,上面也看見了,View動畫無非也就做那幾種事情,別的也搞不定,而屬性動畫就可以的,譬如3D旋轉一張圖片。其實說白了,你記住一點就行,屬性動畫實現原理就是修改控件的屬性值實現的動畫。

              具體先看下類關系:

              /**
               * This is the superclass for classes which provide basic support for animations which can be
               * started, ended, and have AnimatorListeners added to them.
               */
              public abstract class Animator implements Cloneable {
                  ......
              }
              • 1
              • 2
              • 3
              • 4
              • 5
              • 6
              • 7

              所有的屬性動畫的抽象基類就是他。我們看下他的實現子類:
              這裡寫圖片描述
              其實可以看見,屬性動畫的實現有7個類(PS,之所以類繼承關系列表會出來那麼多是因為我下載了所有版本的SDK,你只用關注我紅點標注的就行,妹的,ubuntu下圖片處理工具怎麼都這麼難用),進去粗略分析可以發現,好幾個是hide的類,而其他可用的類繼承關系又如下:

              這裡寫圖片描述

              java類名 xml關鍵字 描述信息 ValueAnimator 放置在res/animator/目錄下 在一個特定的時間裡執行一個動畫 TimeAnimator 不支持/點我查看原因 時序監聽回調工具 ObjectAnimator 放置在res/animator/目錄下 一個對象的一個屬性動畫 AnimatorSet 放置在res/animator/目錄下 動畫集合

              所以可以看見,我們平時使用屬性動畫的重點就在於AnimatorSet、ObjectAnimator、TimeAnimator、ValueAnimator。所以接下來我們就來依次說說如何使用。

              4-2 屬性動畫詳細說明

              4-2-1 屬性動畫計算原理

              參看Android官方文檔,英文原版詳情點我查看!

              Android屬性動畫(注意最低兼容版本,不過可以使用開源項目來替代低版本問題)提供了以下屬性:

              • Duration:動畫的持續時間;
              • TimeInterpolation:定義動畫變化速率的接口,所有插值器都必須實現此接口,如線性、非線性插值器;
              • TypeEvaluator:用於定義屬性值計算方式的接口,有int、float、color類型,根據屬性的起始、結束值和插值一起計算出當前時間的屬性值;
              • Animation sets:動畫集合,即可以同時對一個對象應用多個動畫,這些動畫可以同時播放也可以對不同動畫設置不同的延遲;
              • Frame refreash delay:多少時間刷新一次,即每隔多少時間計算一次屬性值,默認為10ms,最終刷新時間還受系統進程調度與硬件的影響;
              • Repeat Country and behavoir:重復次數與方式,如播放3次、5次、無限循環,可以讓此動畫一直重復,或播放完時向反向播放;

                接下來先來看官方為了解釋原理給出的兩幅圖(其實就是初中物理題,不解釋):

                這裡寫圖片描述
                上面就是一個線性勻速動畫,描述了一個Object的X屬性運動動畫,該對象的X坐標在40ms內從0移動到40,每10ms刷新一次,移動4次,每次移動為40/4=10pixel。
                這裡寫圖片描述
                上面是一個非勻速動畫,描述了一個Object的X屬性運動動畫,該對象的X坐標在40ms內從0移動到40,每10ms刷新一次,移動4次,但是速率不同,開始和結束的速度要比中間部分慢,即先加速後減速。

                接下來我們來詳細的看一下,屬性動畫系統的重要組成部分是如何計算動畫值的,下圖描述了如上面所示動畫的實現作用過程。

                這裡寫圖片描述

                其中的ValueAnimator是動畫的執行類,跟蹤了當前動畫的執行時間和當前時間下的屬性值;ValueAnimator封裝了動畫的TimeInterpolator時間插值器和一個TypeEvaluator類型估值,用於設置動畫屬性的值,就像上面圖2非線性動畫裡,TimeInterpolator使用了AccelerateDecelerateInterpolator、TypeEvaluator使用了IntEvaluator。

                為了執行一個動畫,你需要創建一個ValueAnimator,並且指定目標對象屬性的開始、結束值和持續時間。在調用start後,整個動畫過程中, ValueAnimator會根據已經完成的動畫時間計算得到一個0到1之間的分數,代表該動畫的已完成動畫百分比。0表示0%,1表示100%,譬如上面圖一線性勻速動畫中總時間 t = 40 ms,t = 10 ms的時候是 0.25。

                當ValueAnimator計算完已完成動畫分數後,它會調用當前設置的TimeInterpolator,去計算得到一個interpolated(插值)分數,在計算過程中,已完成動畫百分比會被加入到新的插值計算中。如上圖2非線性動畫中,因為動畫的運動是緩慢加速的,它的插值分數大約是 0.15,小於t = 10ms時的已完成動畫分數0.25。而在上圖1中,這個插值分數一直和已完成動畫分數是相同的。

                當插值分數計算完成後,ValueAnimator會根據插值分數調用合適的 TypeEvaluator去計算運動中的屬性值。

                好了,現在我們來看下代碼就明白這段話了,上面圖2非線性動畫裡,TimeInterpolator使用了AccelerateDecelerateInterpolator、TypeEvaluator使用了IntEvaluator。所以這些類都是標准的API,我們來看下標准API就能類比自己寫了,如下:

                首先計算已完成動畫時間分數(以10ms為例):t=10ms/40ms=0.25。

                接著看如下源碼如何實現計算差值分數的:

                public class AccelerateDecelerateInterpolator extends BaseInterpolator
                        implements NativeInterpolatorFactory {
                    public AccelerateDecelerateInterpolator() {
                    }
                    ......
                    //這是我們關注重點,可以發現如下計算公式計算後(input即為時間因子)插值大約為0.15。
                    public float getInterpolation(float input) {
                        return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
                    }
                    ......
                }
                • 1
                • 2
                • 3
                • 4
                • 5
                • 6
                • 7
                • 8
                • 9
                • 10
                • 11

                其實AccelerateDecelerateInterpolator的基類接口就是TimeInterpolator,如下,他只有getInterpolation方法,也就是上面我們關注的方法。

                public interface TimeInterpolator {
                    float getInterpolation(float input);
                }
                • 1
                • 2
                • 3

                接著ValueAnimator會根據插值分數調用合適的TypeEvaluator(IntEvaluator)去計算運動中的屬性值,如下,因為startValue = 0,所以屬性值:0+0.15*(40-0)= 6。

                public class IntEvaluator implements TypeEvaluator<Integer> {
                    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
                        int startInt = startValue;
                        return (int)(startInt + fraction * (endValue - startInt));
                    }
                }
                • 1
                • 2
                • 3
                • 4
                • 5
                • 6

                這就是官方給的一個關於屬性動畫實現的過程及基本原理解釋,相信你看到這裡是會有些迷糊的,沒關系,你先有個大致概念就行,接下來我們會慢慢進入實戰,因為Android的屬性動畫相對於其他動畫來說涉及的知識點本來就比較復雜,所以我們慢慢來。

                4-2-2 XML方式屬性動畫

                在xml中可直接用的屬性動畫節點有ValueAnimator、ObjectAnimator、AnimatorSet。如下是官方的一個例子和解釋(詳情點我):

                <set
                  android:ordering=["together" | "sequentially"]>
                
                    <objectAnimator
                        android:propertyName="string"
                        android:duration="int"
                        android:valueFrom="float | int | color"
                        android:valueTo="float | int | color"
                        android:startOffset="int"
                        android:repeatCount="int"
                        android:repeatMode=["repeat" | "reverse"]
                        android:valueType=["intType" | "floatType"]/>
                
                    <animator
                        android:duration="int"
                        android:valueFrom="float | int | color"
                        android:valueTo="float | int | color"
                        android:startOffset="int"
                        android:repeatCount="int"
                        android:repeatMode=["repeat" | "reverse"]
                        android:valueType=["intType" | "floatType"]/>
                
                    <set>
                        ...
                    set>
                set>
                • 1
                • 2
                • 3
                • 4
                • 5
                • 6
                • 7
                • 8
                • 9
                • 10
                • 11
                • 12
                • 13
                • 14
                • 15
                • 16
                • 17
                • 18
                • 19
                • 20
                • 21
                • 22
                • 23
                • 24
                • 25
                • 26

                屬性解釋:

                xml屬性 解釋 android:ordering 控制子動畫啟動方式是先後有序的還是同時進行。sequentially:動畫按照先後順序;together(默認):動畫同時啟動;


                屬性解釋:

                xml屬性 解釋 android:propertyName String類型,必須要設置的節點屬性,代表要執行動畫的屬性(通過名字引用),辟如你可以指定了一個View的”alpha” 或者 “backgroundColor” ,這個objectAnimator元素沒有對外說明target屬性,所以你不能在XML中設置執行這個動畫,必須通過調用loadAnimator()方法加載你的XML動畫資源,然後調用setTarget()應用到具備這個屬性的目標對象上(譬如TextView)。 android:valueTo float、int或者color類型,必須要設置的節點屬性,表明動畫結束的點;如果是顏色的話,由6位十六進制的數字表示。 android:valueFrom 相對應valueTo,動畫的起始點,如果沒有指定,系統會通過屬性的get方法獲取,顏色也是6位十六進制的數字表示。 android:duration 動畫的時長,int類型,以毫秒為單位,默認為300毫秒。 android:startOffset 動畫延遲的時間,從調用start方法後開始計算,int型,毫秒為單位。 android:repeatCount 一個動畫的重復次數,int型,”-1“表示無限循環,”1“表示動畫在第一次執行完成後重復執行一次,也就是兩次,默認為0,不重復執行。 android:repeatMode 重復模式:int型,當一個動畫執行完的時候應該如何處理。該值必須是正數或者是-1,“reverse”會使得按照動畫向相反的方向執行,可實現類似鐘擺效果。“repeat”會使得動畫每次都從頭開始循環。 android:valueType 關鍵參數,如果該value是一個顏色,那麼就不需要指定,因為動畫框架會自動的處理顏色值。有intType和floatType(默認)兩種:分別說明動畫值為int和float型。


                屬性解釋:
                同上屬性,不多介紹。

                XML屬性動畫使用方法:

                AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
                    R.animtor.property_animator);
                set.setTarget(myObject);
                set.start();
                • 1
                • 2
                • 3
                • 4

                4-2-3 Java方式屬性動畫

                1、ObjectAnimator:繼承自ValueAnimator,允許你指定要進行動畫的對象以及該對象的一個屬性。該類會根據計算得到的新值自動更新屬性。大多數的情況使用ObjectAnimator就足夠了,因為它使得目標對象動畫值的處理過程變得足夠簡單,不用像ValueAnimator那樣自己寫動畫更新的邏輯,但是ObjectAnimator有一定的限制,比如它需要目標對象的屬性提供指定的處理方法(譬如提供getXXX,setXXX方法),這時候你就需要根據自己的需求在ObjectAnimator和ValueAnimator中看哪種實現更方便了。

                ObjectAnimator類提供了ofInt、ofFloat、ofObject這個三個常用的方法,這些方法都是設置動畫作用的元素、屬性、開始、結束等任意屬性值。當屬性值(上面方法的參數)只設置一個時就把通過getXXX反射獲取的值作為起點,設置的值作為終點;如果設置兩個(參數),那麼一個是開始、另一個是結束。
                
                特別注意:ObjectAnimator的動畫原理是不停的調用setXXX方法更新屬性值,所有使用ObjectAnimator更新屬性時的前提是Object必須聲明有getXXX和setXXX方法。
                

                我們通常使用ObjectAnimator設置View已知的屬性來生成動畫,而一般View已知屬性變化時都會主動觸發重繪圖操作,所以動畫會自動實現;但是也有特殊情況,譬如作用Object不是View,或者作用的屬性沒有觸發重繪,或者我們在重繪時需要做自己的操作,那都可以通過如下方法手動設置:

                ObjectAnimator mObjectAnimator= ObjectAnimator.ofInt(view, "customerDefineAnyThingName", 0,  1).setDuration(2000);
                mObjectAnimator.addUpdateListener(new AnimatorUpdateListener()
                        {
                            @Override
                            public void onAnimationUpdate(ValueAnimator animation)
                            {
                                //int value = animation.getAnimatedValue();  可以獲取當前屬性值
                                //view.postInvalidate();  可以主動刷新
                                //view.setXXX(value);
                                //view.setXXX(value);
                                //......可以批量修改屬性
                            }
                        });
                • 1
                • 2
                • 3
                • 4
                • 5
                • 6
                • 7
                • 8
                • 9
                • 10
                • 11
                • 12
                • 13

                如下是一個我在項目中的Y軸3D旋轉動畫實現實例:

                ObjectAnimator.ofFloat(view, "rotationY", 0.0f, 360.0f).setDuration(1000).start();
                • 1

                2、PropertyValuesHolder:多屬性動畫同時工作管理類。有時候我們需要同時修改多個屬性,那就可以用到此類,具體如下:

                PropertyValuesHolder a1 = PropertyValuesHolder.ofFloat("alpha", 0f, 1f);  
                PropertyValuesHolder a2 = PropertyValuesHolder.ofFloat("translationY", 0, viewWidth);  
                ......
                ObjectAnimator.ofPropertyValuesHolder(view, a1, a2, ......).setDuration(1000).start();
                • 1
                • 2
                • 3
                • 4

                如上代碼就可以實現同時修改多個屬性的動畫啦。

                3、ValueAnimator:屬性動畫中的時間驅動,管理著動畫時間的開始、結束屬性值,相應時間屬性值計算方法等。包含所有計算動畫值的核心函數以及每一個動畫時間節點上的信息、一個動畫是否重復、是否監聽更新事件等,並且還可以設置自定義的計算類型。

                特別注意:ValueAnimator只是動畫計算管理驅動,設置了作用目標,但沒有設置屬性,需要通過updateListener裡設置屬性才會生效。
                
                ValueAnimator animator = ValueAnimator.ofFloat(0, mContentHeight);  //定義動畫
                animator.setTarget(view);   //設置作用目標
                animator.setDuration(5000).start();
                animator.addUpdateListener(new AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation){
                        float value = (float) animation.getAnimatedValue();
                        view.setXXX(value);  //必須通過這裡設置屬性值才有效
                        view.mXXX = value;  //不需要setXXX屬性方法
                    }
                });
                • 1
                • 2
                • 3
                • 4
                • 5
                • 6
                • 7
                • 8
                • 9
                • 10
                • 11

                大眼看上去可以發現和ObjectAnimator沒啥區別,實際上正是由於ValueAnimator不直接操作屬性值,所以要操作對象的屬性可以不需要setXXX與getXXX方法,你完全可以通過當前動畫的計算去修改任何屬性。

                4、AnimationSet:動畫集合,提供把多個動畫組合成一個組合的機制,並可設置動畫的時序關系,如同時播放、順序播放或延遲播放。具體使用方法比較簡單,如下:

                ObjectAnimator a1 = ObjectAnimator.ofFloat(view, "alpha", 1.0f, 0f);  
                ObjectAnimator a2 = ObjectAnimator.ofFloat(view, "translationY", 0f, viewWidth);  
                ......
                AnimatorSet animSet = new AnimatorSet();  
                animSet.setDuration(5000);  
                animSet.setInterpolator(new LinearInterpolator());   
                //animSet.playTogether(a1, a2, ...); //兩個動畫同時執行  
                animSet.play(a1).after(a2); //先後執行
                ......//其他組合方式
                animSet.start();  
                • 1
                • 2
                • 3
                • 4
                • 5
                • 6
                • 7
                • 8
                • 9
                • 10

                5、Evaluators相關類解釋:Evaluators就是屬性動畫系統如何去計算一個屬性值。它們通過Animator提供的動畫的起始和結束值去計算一個動畫的屬性值。

                • IntEvaluator:整數屬性值。

                • FloatEvaluator:浮點數屬性值。

                • ArgbEvaluator:十六進制color屬性值。

                • TypeEvaluator:用戶自定義屬性值接口,譬如對象屬性值類型不是int、float、color類型,你必須實現這個接口去定義自己的數據類型。

                  既然說到這了,那就來個例子吧,譬如我們需要實現一個自定義屬性類型和計算規則的屬性動畫,如下類型float[]:

                  ValueAnimator valueAnimator = new ValueAnimator();
                  valueAnimator.setDuration(5000);
                  valueAnimator.setObjectValues(new float[2]); //設置屬性值類型
                  valueAnimator.setInterpolator(new LinearInterpolator());
                  valueAnimator.setEvaluator(new TypeEvaluator
                  • 1
                  • 2
                  • 3
                  • 4
                  • 5
                  • 6
                  • 7
                  • 8
                  • 9
                  • 10
                  • 11
                  • 12
                  • 13
                  • 14
                  • 15
                  • 16
                  • 17
                  • 18
                  • 19
                  • 20
                  • 21
                  • 22
                  • 23
                  • 24
                  • 25
                  • 26
                  • 27
                  • 28
                  • 29

                  6、Interpolators相關類解釋:

                  • AccelerateDecelerateInterolator:先加速後減速。

                    AccelerateInterpolator:加速。

                    DecelerateInterpolator:減速。

                    AnticipateInterpolator:先向相反方向改變一段再加速播放。

                    AnticipateOvershootInterpolator:先向相反方向改變,再加速播放,會超出目標值然後緩慢移動至目標值,類似於彈簧回彈。

                    BounceInterpolator:快到目標值時值會跳躍。

                    CycleIinterpolator:動畫循環一定次數,值的改變為一正弦函數:Math.sin(2 * mCycles * Math.PI * input)。

                    LinearInterpolator:線性均勻改變。

                    OvershottInterpolator:最後超出目標值然後緩慢改變到目標值。

                    TimeInterpolator:一個允許自定義Interpolator的接口,以上都實現了該接口。

                    舉個例子,就像系統提供的標准API一樣,如下就是加速插值器的實現代碼,我們自定義時也可以類似實現:

                    //開始很慢然後不斷加速的插值器。
                    public class AccelerateInterpolator implements Interpolator {
                        private final float mFactor;
                        private final double mDoubleFactor;
                    
                        public AccelerateInterpolator() {
                            mFactor = 1.0f;
                            mDoubleFactor = 2.0;
                        }
                    
                        ......
                    
                        //input  0到1.0。表示動畫當前點的值,0表示開頭,1表示結尾。
                        //return  插值。值可以大於1超出目標值,也可以小於0突破低值。
                        @Override
                        public float getInterpolation(float input) {
                            //實現核心代碼塊
                            if (mFactor == 1.0f) {
                                return input * input;
                            } else {
                                return (float)Math.pow(input, mDoubleFactor);
                            }
                        }
                    }
                    • 1
                    • 2
                    • 3
                    • 4
                    • 5
                    • 6
                    • 7
                    • 8
                    • 9
                    • 10
                    • 11
                    • 12
                    • 13
                    • 14
                    • 15
                    • 16
                    • 17
                    • 18
                    • 19
                    • 20
                    • 21
                    • 22
                    • 23
                    • 24

                    綜上可以發現,我們可以使用現有系統提供標准的東東實現屬性動畫,也可以通過自定義繼承相關接口實現自己的動畫,只要實現上面提到的那些主要方法即可。

                    4-2-4 Java屬性動畫拓展之ViewPropertyAnimator動畫

                    在Android API 12時,View中添加了animate方法,具體如下:

                    public class View implements Drawable.Callback, KeyEvent.Callback,
                            AccessibilityEventSource {
                         ......
                         /**
                         * This method returns a ViewPropertyAnimator object, which can be used to animate
                         * specific properties on this View.
                         *
                         * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
                         */
                        public ViewPropertyAnimator animate() {
                            if (mAnimator == null) {
                                mAnimator = new ViewPropertyAnimator(this);
                            }
                            return mAnimator;
                        }
                        ......
                    }
                    • 1
                    • 2
                    • 3
                    • 4
                    • 5
                    • 6
                    • 7
                    • 8
                    • 9
                    • 10
                    • 11
                    • 12
                    • 13
                    • 14
                    • 15
                    • 16
                    • 17

                    可以看見通過View的animate()方法可以得到一個ViewPropertyAnimator的屬性動畫(有人說他沒有繼承Animator類,是的,他是成員關系,不是之前那種繼承關系)。

                    ViewPropertyAnimator提供了一種非常方便的方法為View的部分屬性設置動畫(切記,是部分屬性),它可以直接使用一個Animator對象設置多個屬性的動畫;在多屬性設置動畫時,它比 上面的ObjectAnimator更加牛逼、高效,因為他會管理多個屬性的invalidate方法統一調運觸發,而不像上面分別調用,所以還會有一些性能優化。如下就是一個例子:

                    myView.animate().x(0f).y(100f).start(); 
                    • 1

                    4-2-5 Java屬性動畫拓展之LayoutAnimator容器布局動畫

                    Property動畫系統還提供了對ViewGroup中View添加時的動畫功能,我們可以用LayoutTransition對ViewGroup中的View進行動畫設置顯示。LayoutTransition的動畫效果都是設置給ViewGroup,然後當被設置動畫的ViewGroup中添加刪除View時體現出來。該類用於當前布局容器中有View添加、刪除、隱藏、顯示等時候定義布局容器自身的動畫和View的動畫,也就是說當在一個LinerLayout中隱藏一個View的時候,我們可以自定義 整個由於LinerLayout隱藏View而改變的動畫,同時還可以自定義被隱藏的View自己消失時候的動畫等。

                    我們可以發現LayoutTransition類中主要有五種容器轉換動畫類型,具體如下:

                    • LayoutTransition.APPEARING:當View出現或者添加的時候View出現的動畫。

                    • LayoutTransition.CHANGE_APPEARING:當添加View導致布局容器改變的時候整個布局容器的動畫。

                    • LayoutTransition.DISAPPEARING:當View消失或者隱藏的時候View消失的動畫。

                    • LayoutTransition.CHANGE_DISAPPEARING:當刪除或者隱藏View導致布局容器改變的時候整個布局容器的動畫。

                    • LayoutTransition.CHANGE:當不是由於View出現或消失造成對其他View位置造成改變的時候整個布局容器的動畫。

                      XML方式使用系統提供的默認LayoutTransition動畫:

                      我們可以通過如下方式使用系統提供的默認ViewGroup的LayoutTransition動畫:

                      android:animateLayoutChanges=”true”
                      • 1

                      在ViewGroup添加如上xml屬性默認是沒有任何動畫效果的,因為前面說了,該動畫針對於ViewGroup內部東東發生改變時才有效,所以當我們設置如上屬性然後調運ViewGroup的addView、removeView方法時就能看見系統默認的動畫效果了。

                      還有一種就是通過如下方式設置:

                      android:layoutAnimation=”@anim/customer_anim”
                      • 1

                      通過這種方式就能實現很多吊炸天的動畫。

                      Java方式使用系統提供的默認LayoutTransition動畫:

                      在使用LayoutTransition時,你可以自定義這幾種事件類型的動畫,也可以使用默認的動畫,總之最終都是通過setLayoutTransition(LayoutTransition lt)方法把這些動畫以一個LayoutTransition對象設置給一個ViewGroup。

                      譬如實現如上Xml方式的默認系統LayoutTransition動畫如下:

                      mTransitioner = new LayoutTransition();
                      mViewGroup.setLayoutTransition(mTransitioner);
                      • 1
                      • 2

                      稍微再高端一點吧,我們來自定義這幾類事件的動畫,分別實現他們,那麼你可以像下面這麼處理:

                      mTransitioner = new LayoutTransition();
                      ......
                      ObjectAnimator anim = ObjectAnimator.ofFloat(this, "scaleX", 0, 1);
                      ......//設置更多動畫
                      mTransition.setAnimator(LayoutTransition.APPEARING, anim);
                      ......//設置更多類型的動畫                mViewGroup.setLayoutTransition(mTransitioner);
                      • 1
                      • 2
                      • 3
                      • 4
                      • 5
                      • 6

                      到此通過LayoutTransition你就能實現類似小米手機計算器切換普通型和科學型的炫酷動畫了。

                      【工匠若水http://blog.csdn.net/yanbober轉載請注明出處。點我開始Android技術交流】

                      5 Android動畫總結

                      到此Android動畫基本已經描述OK了,也就這麼三大類,尤其是屬性動畫更加一籌。但是特別說一句,上面基本都沒有提及到各種動畫的Listener接口,原因是這個玩意太簡單,所以不提了,相信你會監聽View的onClickListener就一定會觸類旁通動畫的Listener方法的。有了這些基礎相信無論是自定義控件時還是自定義動畫時都會起到直接的指導參考作用。其實對於Android的動畫實現遠遠不止現在提到的這些,但是這些又是基礎,所以後面還會寫文章說說Android提供的其他動畫參考工具類的。

                      現在我們繼續沿用官方的對比,翻譯一下這些動畫的區別,具體如下(點我參看原文How Property Animation Differs from View Animation):

                      View動畫:

                      View動畫只能夠為View添加動畫,如果想為非View對象添加動畫須自己實現;且View動畫支持的種類很少;尤其是他改變的是View的繪制效果,View的屬性沒有改變,其位置與大小都不變;View動畫代碼量少,使用簡單方便。

                      Property動畫:

                      彌補了View動畫的缺陷,你可以為一個對象的任意屬性添加動畫,對象自己的屬性會被真的改變;當對象的屬性變化的時候,屬性動畫會自動刷新屏幕;屬性動畫改變的是對象的真實屬性,而且屬性動畫不止用於View,還可以用於任何對象。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved