Android Animation:這一次讓你完全瞭解 Android Tween Animation

1. 什麼是 Tween Animation?

經過 Animation 對象在圖像上執行一系列的變換而造成的動畫。html

Creates an animation by performing a series of transformations on a single image with an Animationandroid

2. Tween Animation 的做用是什麼?

經過上面的定義可知:算法

Tween Animation 的主要做用是在可視對象上執行一系列的變化操做。express

舉例來講,就是 Tween Animation 能夠改變界面上顯示控件的狀態,如 Button 的顯示、隱藏,ImageView 的尺寸縮放等等。apache

3. Tween Animation 都包括哪幾類動畫,各種動畫的主要做用是什麼?

3.1 Tween Animation 分類

Tween Animation 包括五類動畫,分別是:bash

  1. AlphaAnimation
  2. ScaleAnimation
  3. TranslateAnimation
  4. RotateAnimation
  5. AnimationSet

3.2 各種動畫主要做用

  1. AlphaAnimation

主要用於控制 View 的可見性(顯示|隱藏)。app

  1. ScaleAnimation

主要用於縮放 View 大小。less

  1. TranslateAnimation

主要用於移動 View 的位置。ide

  1. RotateAnimation

主要用於旋轉 View。函數

  1. AnimationSet

某些場景僅靠上面單一類型的動畫是沒法實現的,須要多個類型的動畫組合才能達到最終的效果,此時 AnimationSet 就派上用場了,AnimationSet 的主要做用就是組合各種 Tween Animation。

4. 如何使用 Tween Animation?

建立 Tween Animation 的方式共兩種:

  1. XML
  2. CODE

4.1 經過 XML 建立 Tween Animation

4.1.1 經過 XML 建立 AlphaAnimation
4.1.1.1. 語法
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="integer"
    android:fillAfter="true|false"
    android:fillBefore="true|false"
    android:fillEnabled="true|false"
    android:interpolator="@[package:]anim/interpolator_resource"
    android:repeatCount="infinite|integer"
    android:repeatMode="reverse|restart"
    android:fromAlpha="float"
    android:toAlpha="float" />
複製代碼
4.1.1.2. 屬性詳解
屬性 含義 取值範圍
xmlns:android 聲明 XML 佈局文件屬性命名空間 schemas.android.com/apk/res/and…
android:duration 動畫的執行時間 必須大於等於 0,不然程序將報錯
android:fillAfter 動畫執行完以後是否保留動畫結束時的狀態 true 保存,false 不保存(默認 false)
android:fillBefore 動畫開始執行以前,是否應用動畫的起始狀態 true 應用,false 不該用(默認 true)
android:fillEnabled 該屬性決定了 fillBefore 屬性可否生效 true fillBefore 生效,false fillBefore 不生效(默認)
android:interpolator 插值器,決定了動畫的變化率 Android,Custom
android:repeatCount 動畫重複的次數 整型數字,默認爲 0。當爲負數時,表示無限循環
android:repeatMode 當動畫的執行次數大於 1 時,下一次動畫執行的方式 從新開始(默認),反着執行
android:fromAlpha 動畫開始時的透明度 0 透明,1 不透明
android:toAlpha 動畫結束時的透明度 0 透明,1 不透明
4.1.1.3. 示例
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@integer/integer_one_thousand_and_two_hundred"
    android:fillAfter="true"
    android:fromAlpha="@integer/integer_one"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:repeatCount="infinite"
    android:repeatMode="reverse"
    android:toAlpha="@integer/integer_zero" />
複製代碼

最終效果以下:

4.1.1.4. 部分屬性解釋

4.1.1.4.1. android:fillAfter

動畫執行完以後,是否保留最終的狀態,true 保留,false,不保留。

1.android:fillAfter="false"

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@integer/integer_one_thousand_and_two_hundred"
    android:fillAfter="false"
    android:fromAlpha="@fraction/scale_normal"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:toAlpha="@integer/integer_zero" />
複製代碼
  1. android:fillAfter="true"
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@integer/integer_one_thousand_and_two_hundred"
    android:fillAfter="true"
    android:fromAlpha="@fraction/scale_normal"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:toAlpha="@integer/integer_zero" />
複製代碼

4.1.1.4.2. android:fillBefore

第二次動畫開始執行時,是否從動畫開始的狀態(fromAlpha)開始執行,true 是,false 不是。

原本想解釋下這個屬性和 android:fillEnabled 的,但因爲 AlphaAnimation 應用此屬性時,效果不明顯,因此做罷。

4.1.2 經過 XML 建立 ScaleAnimation
4.1.2.1. 語法
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="integer"
    android:fillAfter="true|false"
    android:fillBefore="true|false"
    android:fillEnabled="true|false"
    android:interpolator="@[package:]anim/interpolator_resource"
    android:repeatCount="infinite|integer"
    android:repeatMode="reverse|restart"
    android:fromXScale="float"
    android:fromYScale="float" 
    android:toXScale="float"
    android:toYScale="float" 
    android:pivotX="float"
    android:pivotY="float"
    />
複製代碼
4.1.2.2. 屬性詳解
屬性 含義 取值範圍
xmlns:android 聲明 XML 佈局文件屬性命名空間 schemas.android.com/apk/res/and…
android:duration 動畫的執行時間 必須大於等於 0,不然程序將報錯
android:fillAfter 動畫執行完以後是否保留動畫結束時的狀態 true 保存,false 不保存(默認 false)
android:fillBefore 動畫開始執行以前,是否應用動畫的起始狀態 true 應用,false 不該用(默認 true)
android:fillEnabled 該屬性決定了 fillBefore 屬性可否生效 true fillBefore 生效,false fillBefore 不生效(默認)
android:interpolator 插值器,決定了動畫的變化率 Android,Custom
android:repeatCount 動畫重複的次數 整型數字,默認爲 0。當爲負數時,表示無限循環
android:repeatMode 當動畫的執行次數大於 1 時,下一次動畫執行的方式 從新開始(默認),反着執行
android:fromXScale 動畫開始時的 X 軸方向上的縮放比例 浮點數,默認值爲 1(大小保持不變)
android:fromYScale 動畫開始時的 Y 軸方向上的縮放比例 浮點數,默認值爲 1(大小保持不變)
android:toXScale 動畫結束時的 X 軸方向上的縮放比例 浮點數,默認值爲 1(大小保持不變)
android:toYScale 動畫結束時的 Y 軸方向上的縮放比例 浮點數,默認值爲 1(大小保持不變)
android:pivotX 動畫執行時 X 軸方向上不變的座標點(軸心) 浮點數,默認值爲縮放對象的左邊
android:pivotY 動畫執行時 Y 軸方向上不變的座標點(軸心) 浮點數,默認值爲縮放對象的上邊
4.1.2.3. 示例
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@integer/integer_one_thousand_and_two_hundred"
    android:fillAfter="true"
    android:fromXScale="@fraction/percent_one_hundred"
    android:fromYScale="@fraction/percent_one_hundred"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:pivotX="@fraction/percent_fifty"
    android:pivotY="@fraction/percent_fifty"
    android:repeatCount="infinite"
    android:repeatMode="reverse"
    android:toXScale="@fraction/percent_two_hundred"
    android:toYScale="@fraction/percent_two_hundred" />
複製代碼

最終效果以下:

4.1.2.4. 部分屬性解釋

4.1.2.4.1. android:fillAfter

動畫執行完以後,是否保留最後的狀態,true 保留,false,不保留。

1.android:fillAfter="false"

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="false"
    android:fromXScale="1"
    android:fromYScale="1"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:toXScale="2"
    android:toYScale="2" />
複製代碼

2.android:fillAfter="true"

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fromXScale="1"
    android:fromYScale="1"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:toXScale="2"
    android:toYScale="2" />
複製代碼

4.1.2.4.2. android:fillBefore

第二次動畫開始執行時,是否從動畫開始的狀態(fromXScale,fromYScale)開始執行,true 是,false 不是。

按照開發文檔的說法,fillEnabled 屬性將對 fillBefore 屬性有必定的影響,但我在運行的時候,發現實際上並無什麼影響,即 fillBefore 屬性最終有沒有起做用,跟 fillEnabled 是否是 true 沒有關係(即便當 fillEnabled = false 時,fillBefore = true 仍是起做用)。

  1. android:fillAfter="false"
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="4000"
    android:fillAfter="true"
    android:fillBefore="false"
    android:fromXScale="2"
    android:fromYScale="2"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:toXScale="4"
    android:toYScale="4" />
複製代碼

當第一次動畫執行完畢以後,再此執行動畫的時候,動畫執行的目標對象會從原始狀態(閃一下)跳轉至 from*Scale,而後從 from*Scale 到 to*Scale。

奈何錄製的 GIF 中恰好丟了這一幀,小老弟,你就用心去體會吧。

  1. android:fillAfter="true"
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="4000"
    android:fillAfter="true"
    android:fillBefore="true"
    android:fromXScale="2"
    android:fromYScale="2"
    android:interpolator="@android:anim/linear_interpolator"
    android:toXScale="4"
    android:toYScale="4" />
複製代碼

當第一次動畫執行完畢以後,再此執行動畫的時候,動畫執行的目標對象會直接從 from*Scale 到 to*Scale。

4.1.2.4.3. android:pivotX,android:pivotY

動畫執行目標對象執行縮放動畫時,保持不變的座標點,默認爲目標對象的左上角(動畫執行目標對象左邊與上邊的焦點)。

當 pivotX,pivotY 不爲 0 時,最終的 pivotX 和 pivotY 爲:

pivotX = left(動畫執行目標對象左邊絕對座標) + pivotX
pivotY = top(動畫執行目標對象上邊絕對座標) + pivotY

即最終的軸心點的座標都是相對動畫執行目標對象左邊和上邊而言的。

  1. 默認值
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fillBefore="true"
    android:fromXScale="1"
    android:fromYScale="1"
    android:interpolator="@android:anim/linear_interpolator"
    android:toXScale="2"
    android:toYScale="2" />
複製代碼
  1. android:pivotX="0",android:pivotY="0"
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fillBefore="true"
    android:fromXScale="1"
    android:fromYScale="1"
    android:pivotX="0"
    android:pivotY="0"
    android:interpolator="@android:anim/linear_interpolator"
    android:toXScale="2"
    android:toYScale="2" />
複製代碼

因爲 android:pivotX="0" 和 android:pivotY="0" 均爲 0,因此放大動畫的軸心點還在動畫執行目標對象的左上角。

  1. android:pivotX="50%",android:pivotY="50%"
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fillBefore="true"
    android:fromXScale="1"
    android:fromYScale="1"
    android:pivotX="50%"
    android:pivotY="50%"
    android:interpolator="@android:anim/linear_interpolator"
    android:toXScale="2"
    android:toYScale="2" />
複製代碼

pivotX、pivotY 分別爲動畫執行目標對象寬、高的一半,因此,放大動畫的軸心點是動畫執行目標對象的中心。

  1. android:pivotX="50%p",android:pivotY="50%p"
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fillBefore="true"
    android:fromXScale="1"
    android:fromYScale="1"
    android:pivotX="50%p"
    android:pivotY="50%p"
    android:interpolator="@android:anim/linear_interpolator"
    android:toXScale="0.1"
    android:toYScale="0.1" />
複製代碼

pivotX、pivotY 分別爲動畫執行目標對象父容器寬、高的一半,因此,放大動畫的軸心點是:

pivotX = left + parent width/2
pivotY = top + parent height/2

4.1.3 經過 XML 建立 TranslateAnimation
4.1.3.1. 語法
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="integer"
    android:fillAfter="true|false"
    android:fillBefore="true|false"
    android:fillEnabled="true|false"
    android:interpolator="@[package:]anim/interpolator_resource"
    android:repeatCount="infinite|integer"
    android:repeatMode="reverse|restart"
    android:fromXDelta="float"
    android:fromYDelta="float" 
    android:toXDelta="float"
    android:toYDelta="float" 
    />
複製代碼
4.1.3.2. 屬性詳解
屬性 含義 取值範圍
xmlns:android 聲明 XML 佈局文件屬性命名空間 schemas.android.com/apk/res/and…
android:duration 動畫的執行時間 必須大於等於 0,不然程序將報錯
android:fillAfter 動畫執行完以後是否保留動畫結束時的狀態 true 保存,false 不保存(默認 false)
android:fillBefore 動畫開始執行以前,是否應用動畫的起始狀態 true 應用,false 不該用(默認 true)
android:fillEnabled 該屬性決定了 fillBefore 屬性可否生效 true fillBefore 生效,false fillBefore 不生效(默認)
android:interpolator 插值器,決定了動畫的變化率 Android,Custom
android:repeatCount 動畫重複的次數 整型數字,默認爲 0。當爲負數時,表示無限循環
android:repeatMode 當動畫的執行次數大於 1 時,下一次動畫執行的方式 從新開始(默認),反着執行
android:fromXDelta 動畫開始時的 X 軸方向上的起始座標 浮點數或者百分數。
當爲浮點數時,表示相對於左邊的距離;
當爲百分數時(百分數後不帶 p,如 5%),表示相對於動畫執行目標對象寬度的百分之多少;
當爲百分數時(百分數後帶 p,如 5%p),表示相對於動畫執行目標對象所在父容器寬度的百分之多少;
默認值爲 0。
android:fromYDelta 動畫開始時的 Y 軸方向上的起始座標 浮點數或者百分數。
當爲浮點數時,表示相對於上邊的距離;
當爲百分數時(百分數後不帶 p,如 5%),表示相對於動畫執行目標對象高度的百分之多少;
當爲百分數時(百分數後帶 p,如 5%p),表示相對於動畫執行目標對象所在父容器高度的百分之多少;
默認值爲 0。
android:toXDelta 動畫結束時的 X 軸方向上的結束座標 浮點數或者百分數。
當爲浮點數時,表示相對於左邊的距離;
當爲百分數時(百分數後不帶 p,如 5%),表示相對於動畫執行目標對象寬度的百分之多少;
當爲百分數時(百分數後帶 p,如 5%p),表示相對於動畫執行目標對象所在父容器寬度的百分之多少;
默認值爲 0。
android:toYDelta 動畫結束時的 Y 軸方向上的結束座標 浮點數或者百分數。
當爲浮點數時,表示相對於上邊的距離;
當爲百分數時(百分數後不帶 p,如 5%),表示相對於動畫執行目標對象高度的百分之多少;
當爲百分數時(百分數後帶 p,如 5%p),表示相對於動畫執行目標對象所在父容器高度的百分之多少;
默認值爲 0。
4.1.3.3. 示例
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:interpolator="@anim/overshoot_interpolator"
    android:toXDelta="0"
    android:toYDelta="50%p" />
複製代碼

最終效果以下:

4.1.4 經過 XML 建立 RotateAnimation
4.1.4.1. 語法
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="integer"
    android:fillAfter="true|false"
    android:fillBefore="true|false"
    android:fillEnabled="true|false"
    android:interpolator="@[package:]anim/interpolator_resource"
    android:repeatCount="infinite|integer"
    android:repeatMode="reverse|restart"
    android:fromDegrees="float"
    android:toDegrees="float" 
    android:pivotX="float"
    android:pivotY="float" 
    />
複製代碼
4.1.4.2. 屬性詳解
屬性 含義 取值範圍
xmlns:android 聲明 XML 佈局文件屬性命名空間 schemas.android.com/apk/res/and…
android:duration 動畫的執行時間 必須大於等於 0,不然程序將報錯
android:fillAfter 動畫執行完以後是否保留動畫結束時的狀態 true 保存,false 不保存(默認 false)
android:fillBefore 動畫開始執行以前,是否應用動畫的起始狀態 true 應用,false 不該用(默認 true)
android:fillEnabled 該屬性決定了 fillBefore 屬性可否生效 true fillBefore 生效,false fillBefore 不生效(默認)
android:interpolator 插值器,決定了動畫的變化率 Android,Custom
android:repeatCount 動畫重複的次數 整型數字,默認爲 0。當爲負數時,表示無限循環
android:repeatMode 當動畫的執行次數大於 1 時,下一次動畫執行的方式 從新開始(默認),反着執行
android:fromDegrees 動畫開始時的角度 浮點數,默認值爲 0
android:toDegrees 動畫結束時的角度 浮點數,默認值爲 0
android:pivotX 動畫執行時 X 軸方向上旋轉中心(軸心) 浮點數,默認值爲旋轉對象的左邊
android:pivotY 動畫執行時 Y 軸方向上旋轉中心(軸心) 浮點數,默認值爲旋轉對象的上邊
4.1.4.2. 示例
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fromDegrees="0"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:toDegrees="360" />
複製代碼

最終效果以下:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fromDegrees="0"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:pivotX="0"
	android:pivotY="0"
    android:toDegrees="360" />
複製代碼

最終效果以下:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fromDegrees="0"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:pivotX="50%"
	android:pivotY="50%"
    android:toDegrees="360" />
複製代碼

最終效果以下:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fromDegrees="0"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:pivotX="50%p"
	android:pivotY="50%p"
    android:toDegrees="360" />
複製代碼

最終效果以下:

由上面幾個示例不難看出,此處的 pivot* 和 ScaleAnimation 動畫中概念徹底同樣,因此,只要以前理解了這個概念,在這裏也沒有什麼困難,直接用就行了。

4.1.5 經過 XML 建立 AnimationSet
4.1.5.1. 語法
<?xml version="1.0" encoding="utf-8"?>
<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>
複製代碼
4.1.5.2. 屬性詳解
屬性 含義 取值範圍
xmlns:android 聲明 XML 佈局文件屬性命名空間 schemas.android.com/apk/res/and…
android:interpolator 插值器,決定了動畫的變化率 Android,Custom
android:shareInterpolator 多個子動畫是否共用插值器 true 共用,false 不共用(默認)
4.1.5.3. 示例
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@integer/integer_three_thousand"
    android:fillAfter="true"
    android:shareInterpolator="true">
    <translate
        android:fromXDelta="@integer/integer_zero"
        android:fromYDelta="@integer/integer_zero"
        android:toXDelta="@integer/integer_zero"
        android:toYDelta="@integer/integer_two_hundred" />
    <alpha
        android:fromAlpha="@integer/integer_one"
        android:toAlpha="@fraction/scale_smaller" />
    <rotate
        android:fromDegrees="@integer/integer_zero"
        android:pivotX="@fraction/percent_fifty"
        android:pivotY="@fraction/percent_fifty"
        android:toDegrees="@integer/integer_seven_hundred_and_five" />
</set>
複製代碼

最終效果以下:

4.2 經過 CODE 建立 Tween Animation

在 Android 中,大多數狀況下,能經過 XML 實現的功能幾乎也能經過代碼實現,接下來,讓咱們看下如何經過代碼實現上面的動畫。

4.2.1 經過 CODE 建立 AlphaAnimation
4.2.1.1. 語法
AlphaAnimation alphaAnimation = new AlphaAnimation(float fromAlpha, float toAlpha);
alphaAnimation.setInterpolator(Interpolator i);
alphaAnimation.setDuration(long durationMillis);
AnimationTarget.startAnimation(alphaAnimation);
複製代碼
4.2.1.2. 示例
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.1f);
alphaAnimation.setInterpolator(new AccelerateInterpolator());
alphaAnimation.setFillAfter(mIsSaveAnimationState);
alphaAnimation.setDuration(800);
mTarget.startAnimation(alphaAnimation);
複製代碼

最終效果以下:

4.2.2 經過 CODE 建立 ScaleAnimation
4.2.2.1. 語法
ScaleAnimation scaleAnimation = new ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue);
scaleAnimation.setInterpolator(Interpolator i);
scaleAnimation.setDuration(long durationMillis);
AnimationTarget.startAnimation(scaleAnimation); 
複製代碼
4.2.2.2. 示例
ScaleAnimation scaleAnimation = new ScaleAnimation(1f, 2f, 1f, 2f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setInterpolator(new AccelerateInterpolator());
scaleAnimation.setFillAfter(mIsSaveAnimationState);
scaleAnimation.setDuration(800);
mTarget.startAnimation(scaleAnimation);
複製代碼

最終效果以下:

4.2.3 經過 CODE 建立 TranslateAnimation
4.2.3.1. 語法
TranslateAnimation translateAnimation = new TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta);
translateAnimation.setInterpolator(Interpolator i);
translateAnimation.setDuration(long durationMillis);
AnimationTarget.startAnimation(translateAnimation); 
複製代碼
4.2.3.2. 示例
TranslateAnimation translateAnimation = new TranslateAnimation(0f, 200f, 0f, 200f);
translateAnimation.setInterpolator(new AccelerateInterpolator());
translateAnimation.setFillAfter(mIsSaveAnimationState);
translateAnimation.setDuration(800);
mTarget.startAnimation(translateAnimation);
複製代碼

最終效果以下:

4.2.4 經過 CODE 建立 RotateAnimation
4.2.4.1. 語法
RotateAnimation rotateAnimation = new RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue);
rotateAnimation.setInterpolator(Interpolator i);
rotateAnimation.setDuration(long durationMillis);
AnimationTarget.startAnimation(rotateAnimation); 
複製代碼
4.2.4.2. 示例
RotateAnimation rotateAnimation = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setInterpolator(new AccelerateInterpolator());
rotateAnimation.setFillAfter(mIsSaveAnimationState);
rotateAnimation.setDuration(800);
mTarget.startAnimation(rotateAnimation);
複製代碼

最終效果以下:

4.2.5 經過 CODE 建立 AnimationSet
4.2.5.1. 語法
AnimationSet animationSet = new AnimationSet(boolean shareInterpolator);
animationSet.addAnimation(Animation a)
...
AnimationTarget.startAnimation(animationSet);
複製代碼
4.2.5.2. 示例
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.5f);
alphaAnimation.setInterpolator(new AccelerateInterpolator());
alphaAnimation.setFillAfter(mIsSaveAnimationState);
alphaAnimation.setDuration(800);

ScaleAnimation scaleAnimation = new ScaleAnimation(1f, 2f, 1f, 2f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setInterpolator(new AccelerateInterpolator());
scaleAnimation.setFillAfter(mIsSaveAnimationState);
scaleAnimation.setDuration(800);

RotateAnimation rotateAnimation = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setInterpolator(new AccelerateInterpolator());
rotateAnimation.setFillAfter(mIsSaveAnimationState);
rotateAnimation.setDuration(800);

AnimationSet animationSet = new AnimationSet(false);
animationSet.setFillAfter(true);
animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(rotateAnimation);
mTarget.startAnimation(animationSet);
複製代碼

最終效果以下:

5. 自定義插值器

5.1 什麼是插值器,插值器的做用是什麼?

插值器是動畫執行速率調節器,主要用來控制動畫的變化率。

5.2 經常使用的插值器有哪些?

5.2.1 經常使用插值器彙總
類名 ID 做用
AccelerateDecelerateInterpolator @android:anim/accelerate_decelerate_interpolator 加速,減速
AccelerateInterpolator @android:anim/accelerate_interpolator 加速
AnticipateInterpolator @android:anim/anticipate_interpolator 迂迴,加速
AnticipateOvershootInterpolator @android:anim/anticipate_overshoot_interpolator 迂迴,加速超出,返回終點
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 加速 超出,返回終點
5.2.2 插值器示例
5.2.2.1 AccelerateDecelerateInterpolator
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fillBefore="false"
    android:fillEnabled="false"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:toXDelta="40%p"
    android:toYDelta="0" />
複製代碼

最終效果以下:

5.2.2.2 AccelerateInterpolator
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fillBefore="false"
    android:fillEnabled="false"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:interpolator="@android:anim/anticipate_interpolator"
    android:toXDelta="40%p"
    android:toYDelta="0" />
複製代碼

最終效果以下:

5.2.2.3 AnticipateInterpolator
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fillBefore="false"
    android:fillEnabled="false"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:interpolator="@android:anim/anticipate_overshoot_interpolator"
    android:toXDelta="40%p"
    android:toYDelta="0" />
複製代碼

最終效果以下:

5.2.2.4 AnticipateOvershootInterpolator
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fillBefore="false"
    android:fillEnabled="false"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:interpolator="@android:anim/anticipate_overshoot_interpolator"
    android:toXDelta="40%p"
    android:toYDelta="0" />
複製代碼

最終效果以下:

5.2.2.5 BounceInterpolator
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fillBefore="false"
    android:fillEnabled="false"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:interpolator="@android:anim/bounce_interpolator"
    android:toXDelta="40%p"
    android:toYDelta="0" />
複製代碼

最終效果以下:

5.2.2.6 CycleInterpolator
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fillBefore="false"
    android:fillEnabled="false"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:interpolator="@android:anim/cycle_interpolator"
    android:toXDelta="40%p"
    android:toYDelta="0" />
複製代碼

最終效果以下:

5.2.2.7 DecelerateInterpolator
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fillBefore="false"
    android:fillEnabled="false"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:interpolator="@android:anim/decelerate_interpolator"
    android:toXDelta="40%p"
    android:toYDelta="0" />
複製代碼

最終效果以下:

5.2.2.8 LinearInterpolator
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fillBefore="false"
    android:fillEnabled="false"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:interpolator="@android:anim/linear_interpolator"
    android:toXDelta="40%p"
    android:toYDelta="0" />
複製代碼

最終效果以下:

5.2.2.9 OvershootInterpolator
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fillBefore="false"
    android:fillEnabled="false"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:interpolator="@android:anim/overshoot_interpolator"
    android:toXDelta="40%p"
    android:toYDelta="0" />
複製代碼

最終效果以下:

5.3 自定義插值器的方式有哪些?

自定義插值器的方式有兩種:

  1. XML
  2. CODE

5.4 如何自定義插值器

5.4.1. 經過 XML 自定義插值器

經過 XML 自定義插值器的時候,限制性比較大,由於系統只提供了部分插值器的自定義,如 AccelerateInterpolator,有些插值器是不支持自定義的,如 AccelerateDecelerateInterpolator。

接下來,咱們就學習下如何自定義 AccelerateInterpolator。

AccelerateInterpolator 中能夠自定義的屬性只有:android:factor

android:factor 加速的比率(The acceleration rate),默認值爲 1。
複製代碼
  1. 默認值
<!-- accelerateInterpolator --> 
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License"); 
** you may not use this file except in compliance with the License. 
** You may obtain a copy of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** Unless required by applicable law or agreed to in writing, software 
** distributed under the License is distributed on an "AS IS" BASIS, 
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
** See the License for the specific language governing permissions and 
** limitations under the License.
*/
-->

<accelerateInterpolator />


<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fillBefore="false"
    android:fillEnabled="false"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:toXDelta="40%p"
    android:toYDelta="0" />
複製代碼

最終效果以下:

  1. 自定義
<!-- custom accelerateInterpolator --> 
<?xml version="1.0" encoding="utf-8"?>
<accelerateInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:factor="4.0" />


<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1200"
    android:fillAfter="true"
    android:fillBefore="false"
    android:fillEnabled="false"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:interpolator="@android:anim/custom_accelerate_interpolator"
    android:toXDelta="40%p"
    android:toYDelta="0" />
複製代碼

最終效果以下:

能夠經過 XML 自定義插值器,除了 AccelerateInterpolator,還有不少,如下是具體列表:

序號 類名
1 AccelerateInterpolator
2 AnticipateInterpolator
3 AnticipateOvershootInterpolator
4 CycleInterpolator
5 DecelerateInterpolator
6 OvershootInterpolator

5.4.2. 經過 CODE 自定義插值器

相對於經過 XML 自定義插值器而言,經過 CODE 自定義插值器就沒有那麼多限制,能夠說惟一能限制你的是你的想象力。

經過代碼自定義插值器其實也很簡單,只要實現 Interpolator 接口,並實現其中的方法(getInterpolation)就行了。接下來,咱們先看下 Google 官方是如何實現插值器的。

//AccelerateDecelerateInterpolator

package android.view.animation;

import android.content.Context;
import android.util.AttributeSet;

import com.android.internal.view.animation.HasNativeInterpolator;
import com.android.internal.view.animation.NativeInterpolatorFactory;
import com.android.internal.view.animation.NativeInterpolatorFactoryHelper;

/**
 * An interpolator where the rate of change starts and ends slowly but
 * accelerates through the middle.
 */
@HasNativeInterpolator
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();
    }
}
複製代碼

上面是 AccelerateDecelerateInterpolator 的具體實現,經過代碼可知,AccelerateDecelerateInterpolator 是經過餘弦函數實現的:

上圖中用藍色框圈出的部分即爲 AccelerateDecelerateInterpolator 具體算法實現。

明白了上面的道理以後,咱們就能夠自定義插值器。既然 Google 提供了 AccelerateDecelerateInterpolator,那咱們就來實現一個 DecelerateAccelerateInterpolator。

由 AccelerateDecelerateInterpolator 應用的函數曲線圖能夠發現,在 AccelerateDecelerateInterpolator 中,加速的過程是函數曲線斜率逐漸增大的過程,減速的過程是函數曲線斜率逐漸減少的過程。明白這個以後,如何自定義 DecelerateAccelerateInterpolator 就更明確了:

找一個開始時斜率逐漸減少,當過了某個臨界點以後,斜率又逐漸增長的曲線。

大概就是下面這個樣子:

趕忙回憶下,在咱們初、高中學習的過程當中有沒有哪一個函數的曲線跟上面的這個類似的?固然有,三次函數和正切函數。接下來,咱們用正切函數實現。

上圖中用藍色框圈出的部分便是 DecelerateAccelerateInterpolator 實現的理論基礎,接下來,只須要在對這個函數稍做修改便可:

  1. Interpolator 接口中 getInterpolation 方法中 input 的取值範圍爲 [0,1],而藍色框圈出的 X 的取值範圍爲 [-π/4,π/4],因此,須要將 [0,1] 轉換爲 [-π/4,π/4]:

π/2 * input - π/4

  1. 正切函數在 [-π/4,π/4] 取值範圍內,相應的函數值的取值範圍爲[-1,1],而 getInterpolation 最終返回值的取值範圍爲 [0,1],因此,須要將 [-1,1] 轉換爲 [0,1]:

(tan(π/2 * input - π/4) + 1)/2

所以最終的實現爲:

public class DecelerateAccelerateInterpolator implements Interpolator {

    @Override
    public float getInterpolation(float input) {
        return (float) ((Math.tan(Math.PI/2 * input - Math.PI/4) + 1)/2);
    }

}
複製代碼
TranslateAnimation translateAnimation = new TranslateAnimation(0f, 0f, 0f, 800f);
translateAnimation.setInterpolator(new DecelerateAccelerateInterpolator());
translateAnimation.setFillAfter(mIsSaveAnimationState);
translateAnimation.setDuration(1800);
mTarget.startAnimation(translateAnimation);
複製代碼

最終效果以下:

6. 應用實例

Tween Animation 應用場景仍是不少的,如控制界面中元素的顯示、隱藏:

我在這裏只是拋磚引玉而已,具體如何使用,還要靠你們發揮本身的想象力。

7. 參考文獻

  1. Animation resources
  2. Interpolator
  3. 強大繪圖工具
相關文章
相關標籤/搜索