經過 Animation 對象在圖像上執行一系列的變換而造成的動畫。html
Creates an animation by performing a series of transformations on a single image with an Animationandroid
經過上面的定義可知:算法
Tween Animation 的主要做用是在可視對象上執行一系列的變化操做。express
舉例來講,就是 Tween Animation 能夠改變界面上顯示控件的狀態,如 Button 的顯示、隱藏,ImageView 的尺寸縮放等等。apache
Tween Animation 包括五類動畫,分別是:bash
主要用於控制 View 的可見性(顯示|隱藏)。app
主要用於縮放 View 大小。less
主要用於移動 View 的位置。ide
主要用於旋轉 View。函數
某些場景僅靠上面單一類型的動畫是沒法實現的,須要多個類型的動畫組合才能達到最終的效果,此時 AnimationSet 就派上用場了,AnimationSet 的主要做用就是組合各種 Tween Animation。
建立 Tween Animation 的方式共兩種:
<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" />
複製代碼
屬性 | 含義 | 取值範圍 |
---|---|---|
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 不透明 |
<?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.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" />
複製代碼
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 應用此屬性時,效果不明顯,因此做罷。
<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"
/>
複製代碼
屬性 | 含義 | 取值範圍 |
---|---|---|
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 軸方向上不變的座標點(軸心) | 浮點數,默認值爲縮放對象的上邊 |
<?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.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 仍是起做用)。
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 中恰好丟了這一幀,小老弟,你就用心去體會吧。
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
即最終的軸心點的座標都是相對動畫執行目標對象左邊和上邊而言的。
<?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" />
複製代碼
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,因此放大動畫的軸心點還在動畫執行目標對象的左上角。
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 分別爲動畫執行目標對象寬、高的一半,因此,放大動畫的軸心點是動畫執行目標對象的中心。
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
<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"
/>
複製代碼
屬性 | 含義 | 取值範圍 |
---|---|---|
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。 |
<?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" />
複製代碼
最終效果以下:
<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"
/>
複製代碼
屬性 | 含義 | 取值範圍 |
---|---|---|
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 軸方向上旋轉中心(軸心) | 浮點數,默認值爲旋轉對象的上邊 |
<?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 動畫中概念徹底同樣,因此,只要以前理解了這個概念,在這裏也沒有什麼困難,直接用就行了。
<?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>
複製代碼
屬性 | 含義 | 取值範圍 |
---|---|---|
xmlns:android | 聲明 XML 佈局文件屬性命名空間 | schemas.android.com/apk/res/and… |
android:interpolator | 插值器,決定了動畫的變化率 | Android,Custom |
android:shareInterpolator | 多個子動畫是否共用插值器 | true 共用,false 不共用(默認) |
<?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>
複製代碼
最終效果以下:
在 Android 中,大多數狀況下,能經過 XML 實現的功能幾乎也能經過代碼實現,接下來,讓咱們看下如何經過代碼實現上面的動畫。
AlphaAnimation alphaAnimation = new AlphaAnimation(float fromAlpha, float toAlpha);
alphaAnimation.setInterpolator(Interpolator i);
alphaAnimation.setDuration(long durationMillis);
AnimationTarget.startAnimation(alphaAnimation);
複製代碼
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.1f);
alphaAnimation.setInterpolator(new AccelerateInterpolator());
alphaAnimation.setFillAfter(mIsSaveAnimationState);
alphaAnimation.setDuration(800);
mTarget.startAnimation(alphaAnimation);
複製代碼
最終效果以下:
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);
複製代碼
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);
複製代碼
最終效果以下:
TranslateAnimation translateAnimation = new TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta);
translateAnimation.setInterpolator(Interpolator i);
translateAnimation.setDuration(long durationMillis);
AnimationTarget.startAnimation(translateAnimation);
複製代碼
TranslateAnimation translateAnimation = new TranslateAnimation(0f, 200f, 0f, 200f);
translateAnimation.setInterpolator(new AccelerateInterpolator());
translateAnimation.setFillAfter(mIsSaveAnimationState);
translateAnimation.setDuration(800);
mTarget.startAnimation(translateAnimation);
複製代碼
最終效果以下:
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);
複製代碼
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);
複製代碼
最終效果以下:
AnimationSet animationSet = new AnimationSet(boolean shareInterpolator);
animationSet.addAnimation(Animation a)
...
AnimationTarget.startAnimation(animationSet);
複製代碼
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);
複製代碼
最終效果以下:
插值器是動畫執行速率調節器,主要用來控制動畫的變化率。
類名 | 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 | 加速 超出,返回終點 |
<?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" />
複製代碼
最終效果以下:
<?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" />
複製代碼
最終效果以下:
<?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" />
複製代碼
最終效果以下:
<?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" />
複製代碼
最終效果以下:
<?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" />
複製代碼
最終效果以下:
<?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" />
複製代碼
最終效果以下:
<?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" />
複製代碼
最終效果以下:
<?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" />
複製代碼
最終效果以下:
<?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" />
複製代碼
最終效果以下:
自定義插值器的方式有兩種:
經過 XML 自定義插值器的時候,限制性比較大,由於系統只提供了部分插值器的自定義,如 AccelerateInterpolator,有些插值器是不支持自定義的,如 AccelerateDecelerateInterpolator。
接下來,咱們就學習下如何自定義 AccelerateInterpolator。
AccelerateInterpolator 中能夠自定義的屬性只有:android:factor
android:factor 加速的比率(The acceleration rate),默認值爲 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" />
複製代碼
最終效果以下:
<!-- 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 |
相對於經過 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 實現的理論基礎,接下來,只須要在對這個函數稍做修改便可:
π/2 * input - π/4
(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);
複製代碼
最終效果以下:
Tween Animation 應用場景仍是不少的,如控制界面中元素的顯示、隱藏:
我在這裏只是拋磚引玉而已,具體如何使用,還要靠你們發揮本身的想象力。