分類
Android 官方提供了兩種動畫:
- 屬性動畫(Property Animation)通過改變對象的屬性實現動畫效果;
- 視圖動畫(View Animation)作用于 View 的動畫,視圖動畫又可以分為兩類:
- 幀動畫(Frame Animation)通過一組圖片有序播放實現動畫視覺效果;
- 補間動畫(Tween Animation)通過對視圖進行一系列的動作變化實現動畫效果;
一、幀動畫
幀動畫其實是 Drawable,用作 View 的背景,在 res/drawable 目錄下通過 <animation-list> 標簽定義
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot=""
android:variablePadding=""
android:visible="">
<item android:drawable="" android:duration=""/>
</animation-list>
對應的 Drawable 的子類是 AnimationDrawable 類,構造方法:
public AnimationDrawable()
添加一幀動畫:
public void addFrame(@NonNull Drawable frame, int duration)
獲取到 AnimationDrawable 對象之后調用 start()
方法開始動畫
二、補間動畫
Animation 類位于 android.view.animation 包下,直接子類有五個。
1、Animation
a.xml 屬性
上面列出了 Animation 類的所有 xml 屬性以及相關的方法。
- android:duration:動畫的執行時間,單位毫秒;
- android:fillBefore:動畫結束時畫面停留在此動畫的第一幀; 默認值為 true;
- android:fillAfter:動畫結束是畫面停留在此動畫的最后一幀。默認值為false;
- android:repeatCount:動畫重復執行的次數;
- android:repeatMode:動畫重復執行模式,有 restart 和 reverse 兩種;
- android:startOffset:動畫開始的延遲時間;
- android:detachWallpaper:是否在壁紙上運行;
- android:zAdjustment:被設置動畫的內容運行時在Z軸上的位置(top/bottom/normal),默認為 normal;
- android:interpolator:插值器;
b.監聽器
Animation 類內部定義監聽器 AnimationListener,定義了在動畫開始、結束、重復時的回調方法,通過
setAnimationListener
方法設置。
c.一些 public 方法
除了設置 xml 屬性的 setter 方法之外,還有一些常用的 public 方法:
public void start()
public void startNow()
public void setStartTime(long startTimeMillis)
public void reset()
public void cancel()
//設置動畫背景顏色,如果為 0,則沒有背景
public void setBackgroundColor(@ColorInt int bg)
d.定義
動畫有兩種定義方式,一種是在 res/anim 目錄中定義,通過 AnimationUtils#loadAnimation()
方法加載另一種是直接在代碼中通過構造方法創建對象。
視圖動畫只能給 View 使用,所以是通過 View 的方法開始動畫和清除動畫的
public void startAnimation(Animation animation)
public void clearAnimation()
2、TranslateAnimation(平移動畫)
a.xml 文件定義
在 res/anim 目錄中定義:
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta=""
android:fromYDelta=""
android:toXDelta=""
android:toYDelta=""
>
</translate>
使用 translate
標簽,動畫的起始點和結束點是 View 的左上角坐標,通過偏移量的方式來定義:
- android:fromXDelta="",android:fromYDelta="":起始點 x,y 坐標,可以為** 數值、百分數、百分數p,數值表示當前 View 的左上角加上 數值px 作為起始點,即以 View 左上角為原點的坐標,百分數表示當前 View 的左上角加上 View寬高 * 百分數 作為起始點,百分數p表示當前 View 的左上角加上 父控件寬高 * 百分數 **作為起始點;
- android:toXDelta="", android:toYDelta="":結束點 x,y 坐標,取值同上;
b.代碼定義
public 的構造方法:
public TranslateAnimation (Context context, AttributeSet attrs)
public TranslateAnimation (float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
public TranslateAnimation (int fromXType, float fromXValue, int toXType, float toXValue, int fromYType, float fromYValue, int toYType, float toYValue)
第三個構造方法不僅規定了起始點和結束點 x,y 坐標,還規定了每一個偏移值的類型,類型是在 Animation 類中以靜態常量的方式來定義的:
有三種值 ABSOLUTE(絕對)、RELATIVE_TO_SELF(相對自身)、RELATIVE_TO_PARENT(相對父控件)
默認值為 ABSOLUTE,所以第二個構造方法中的參數為絕對數值
2、ScaleAnimation
a.xml 文件定義
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:pivotX=""
android:pivotY=""
android:fromXScale=""
android:fromYScale=""
android:toXScale=""
android:toYScale=""
>
</scale>
scale
標簽定義,縮放中心點默認為 View 左上角,通過偏移量來定義:
- android:pivotX="",android:pivotY="":縮放中心點 x,y 坐標,可以為** 數值、百分數、百分數p,數值表示當前 View 的左上角加上 數值px 作為中心點,百分數表示當前 View 的左上角加上 View寬高 * 百分數 作為中心點,百分數p表示當前 View 的左上角加上 父控件寬高 * 百分數 **作為中心點;
- android:fromXScale="",android:fromYScale="",android:toXScale="",android:toYScale="":開始時和結束時 x 方向和 y 方向縮放比例,1.0表示無變化;
b.代碼定義
public ScaleAnimation (Context context, AttributeSet attrs)
public ScaleAnimation (float fromX, float toX, float fromY, float toY)
public ScaleAnimation (float fromX, float toX, float fromY, float toY, float pivotX, float pivotY)
public ScaleAnimation (float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
第二個構造方法只確定了縮放比例,縮放中心點默認為 View 左上角;
第三個構造方法除了定義了縮放比例,還定義了絕對數值類型的所方中心點偏移量;
第四個構造方法規定了縮放中心點偏移量的類型;
3、RotateAnimation
a.xml 文件定義
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:pivotX=""
android:pivotY=""
android:fromDegrees=""
android:toDegrees=""
android:drawable=""
android:visible=""
>
</rotate>
使用 rotate
標簽,需要聲明的屬性為旋轉的中心點和旋轉角度:
- android:pivotX="",android:pivotY="":旋轉中心點坐標相對 View 左上角坐標偏移量,取值和默認值和 TranslateAnimation 平移坐標以及 ScaleAnimation 縮放中心點坐標相同;
- android:fromDegrees="",android:toDegrees="":旋轉起始角度和結束角度,正值為順時針度數,負值為逆時針度數;
b.代碼定義
構造方法:
public RotateAnimation (Context context, AttributeSet attrs)
public RotateAnimation (float fromDegrees, float toDegrees)
public RotateAnimation (float fromDegrees, float toDegrees, float pivotX, float pivotY)
public RotateAnimation (float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
第二個構造方法只確定了旋轉角度,旋轉中心點默認為 View 左上角,第二個構造方法旋轉中心點偏移量為絕對數值,第三個構造方法規定了旋轉中心點偏移量的類型;
4.AlphaAnimaion
a.xml 文件定義
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha=""
android:toAlpha=""
>
</alpha>
只需要聲明起始和結束的透明度值,取值為 0.0~1.0,0.0表示全透明,1.0表示完全不透明
b.代碼定義
構造方法:
public AlphaAniamtion(Context context,AttributeSet attrs)
public AlphaAnimation (float fromAlpha, float toAlpha)
5.AnimationSet
a.xml 文件定義
<set xmlns:android="http://schemas.android.com/apk/res/android"
>
...
...
</set>
通過 set
標簽定義,和其它四個 Animation 類的使用方法相同
b.代碼定義
構造方法:
public AnimationSet(Context context, AttributeSet attrs)
public AnimationSet(boolean shareInterpolator)
通過 addAnimation
方法來添加一個動畫
public void addAnimation (Animation a)
6.Interpolate
見下文。
三、屬性動畫
Animator 類位于 android.animation 包下,有兩個直接子類 AnimatorSet 和 ValueAnimator,兩個間接子類 ObjectAnimator 和 TimeAnimator
1、視圖動畫和屬性動畫的區別
- 視圖動畫作用對象只限制為 View,而屬性動畫作用對象不限為
View,可以是任何對象。 - 視圖動畫只能改變 View 的位置或者視覺效果,并不能改變其屬性。
2、Animator
Animator 是一個抽象類,為子類定義了一些方法和接口
public 方法
public void start()
public void cancel()
public void end()
public void pause()
public void resume()
public abstract void setStartDelay(long startDelay);
public abstract Animator setDuration(long duration);
public abstract void setInterpolator(TimeInterpolator value);
public void addListener(AnimatorListener listener)
public void removeListener(AnimatorListener listener)
public void addPauseListener(AnimatorPauseListener listener)
public void removePauseListener(AnimatorPauseListener listener)
public void removeAllListeners()
監聽器
3、ValueAnimator
Animator 同樣有兩種定義方式,一種是通過 xml 文件定義,然后通過 AnimatorInflater#loadAnimator()
方法加載動畫,和補間動畫不同的是在 res/animator 目錄下面,另一種是在代碼中使用相應的方法定義。
xml 文件定義
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration=""
android:interpolator=""
android:repeatCount=""
android:repeatMode=""
android:startOffset=""
android:valueFrom=""
android:valueTo=""
android:valueType="">
</animator>
<animator>
標簽定義的是 ValueAnimator 對象,上面列出了定義動畫時使用到的屬性,其中 android:valueType
屬性聲明了值的類型,有 intType、floatType、colorType、pathType 四種類型。
還可以使用 propertyValuesHolder
和 keyframe
標簽定義 ValueAnimator
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:repeatCount="1"
android:repeatMode="reverse">
<propertyValuesHolder>
<keyframe android:fraction="0" android:value="1"/>
<keyframe android:fraction=".2" android:value=".4"/>
<keyframe android:fraction="1" android:value="0"/>
</propertyValuesHolder>
</animator>
Keyframe
Keyframe 保存有值動畫的一個時間、值對,ValueAnimator 的值從一個 Keyframe 變化到另一個 Keyframe,每一個 Keyframe 也有一個 TimeInterpolate 對象。
Keyframe 有三個成員變量:
//時間
float mFraction;
public float getFraction()
public void setFraction(float fraction)
//值類型
Class mValueType;
public Class getType()
//插值器
private TimeInterpolator mInterpolator = null;
public TimeInterpolator getInterpolator()
public void setInterpolator(TimeInterpolator interpolator)
Keyframe 是一個抽象類,相關的方法返回的是對應的子類對象。
public static Keyframe ofInt(float fraction, int value)
public static Keyframe ofInt(float fraction)
public static Keyframe ofFloat(float fraction, float value)
public static Keyframe ofFloat(float fraction)
public static Keyframe ofObject(float fraction, Object value)
public static Keyframe ofObject(float fraction)
Keyframe 內部定義了三個子類:ObjectKeyframe、IntKeyframe、FloatKeyframe。
看一下 ObjectKeyframe 類的實現:
子類內部又定義了一個成員變量 mValue,在 ObjectKeyframe 中是 Object 類型的,并且重寫了 Keyframe 類的 getValue 和 setValue 方法,在
Keyframe#ofObject
方法就是通過 Objectkeyframe 的構造方法創建了一個對象,在構造函數內部給成員變量 mFraction 和 mValue 賦值,這里的 Object 參數可以為任何類的對象,當 value 為 null 時,默認為 Object 類型。
PropertyValueHolder
PropertyValuesHolder 可以暫存動畫的屬性和值使一個動畫可以同時操作多個屬性,有時可以替代 AnimatorSet。
PropertyValuesHolder 類的幾個重要成員變量:
//屬性名稱
String mPropertyName;
public void setPropertyName(String propertyName)
//值類型
Class mValueType;
//屬性值通過一組 Keyframes 來存儲
Keyframes mKeyframes = null;
public void setKeyframes(Keyframe... values)
//以下三個方法內部通過 Keyframe#ofXXX 方法創建 Keyframe 對象并賦值給成員變量 mKeyframes
public void setIntValues(int... values)
public void setFloatValues(float... values)
public void setObjectValues(Object... values)
PropertyValuesHolder 的兩個構造方法都是 private 的
private PropertyValuesHolder(String propertyName)
private PropertyValuesHolder(Property property)
所以要通過內部的一系列 ofXXX 方法創建 PropertyValuesHolder 對象:
public static PropertyValuesHolder ofInt(String propertyName, int... values)
public static PropertyValuesHolder ofInt(Property<?, Integer> property, int... values)
public static PropertyValuesHolder ofFloat(String propertyName, float... values)
public static PropertyValuesHolder ofFloat(Property<?, Float> property, float... values)
public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator,Object... values)
public static PropertyValuesHolder ofObject(String propertyName,TypeConverter<PointF, ?> converter, Path path)
public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values)
public static PropertyValuesHolder ofKeyframe(Property property, Keyframe... values)
ofXXX 方法創建相應的 PropertyValuesHolder 對象,并通過 PropertyValuesHolder 類的 setXXX 給 mKeyframes 賦值。
public 方法
public void start()
public void cancel()
public void end()
public void resume()
public void pause()
public void reverse()
public Object getAnimatedValue()
public Object getAnimatedValue(String propertyName)
public float getAnimatedFraction()
代碼創建對象
一般不使用 ValueAnimator 的構造方法而是通過 ofXXX 方法:
public static ValueAnimator ofInt(int... values)
public static ValueAnimator ofFloat(float... values)
public static ValueAnimator ofArgb(int... values)
public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values)
ofXXX 方法內部的操作都是創建一個 ValueAnimtor 對象,然后通過 ValueAnimator#setXXXValues 方法把 values 封裝成 PropertyValuesHolder 數組
ValueAnimator 的值是存放在 PropertyValuesHolder 類型的數組成員變量 mValues 中的,數組中的每一個元素表示一個屬性,可以看到在 setIntValues 方法中,當 mValues 不為 null 時,把數組中的第一個 PropertyValuesHolder 元素取出來,然后調用 PropertyValuesHolder#setIntValues 方法,把值設置給該 PropertyValuesHolder 對象,前面已經說過 setXXXValues 方法內部調用 Keyframe#ofXXX 方法,當 mValues 為 null 時,最終是通過 PropertyValuesHolder#ofInt 方法生成 PropertyValuesHolder 對象然后調用了 setValues 方法
setValues 則是生成一個 PropertyValuesHolder 數組,在 ProertyValuesHolder#ofObject 方法中調用了該方法,所以 ValueAnimator 可以通過 ofPropertyValuesHolder 對多個屬性動畫。
監聽
public void addUpdateListener(AnimatorUpdateListener listener)
public void removeAllUpdateListeners()
public void removeUpdateListener(AnimatorUpdateListener listener)
ValueAnimator 內部定義了接口監聽動畫的更新,通過在回調方法中調用參數的 ValueAnimator#getAnimatedValue 方法獲取到值動畫的當前進度所對應的值。
4、ObjectAnimator
xml 文件中定義
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueTo="200"
android:valueType="floatType"
android:propertyName="y"
android:repeatCount="1"
android:repeatMode="reverse"/>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:repeatCount="1"
android:repeatMode="reverse">
<propertyValuesHolder android:propertyName="x" android:valueTo="400"/>
<propertyValuesHolder android:propertyName="y" android:valueTo="200"/>
</objectAnimator>
<propertyValuesHolder android:propertyName="x" >
<keyframe android:fraction="0" android:value="800" />
<keyframe android:fraction=".2"
android:interpolator="@android:anim/accelerate_interpolator"
android:value="1000" />
<keyframe android:fraction="1"
android:interpolator="@android:anim/accelerate_interpolator"
android:value="400" />
</propertyValuesHolder>
<propertyValuesHolder android:propertyName="y" >
<keyframe/>
<keyframe android:fraction=".2"
android:interpolator="@android:anim/accelerate_interpolator"
android:value="300"/>
<keyframe android:interpolator="@android:anim/accelerate_interpolator"
android:value="1000" />
</propertyValuesHolder>
使用 objectAnimaor
標簽,ObjectAnimator 繼承自 ValueAnimator 類,屬性基本和 animaor 的定義差不多,只是多出了 android:propertyName
、android:propertyXName=""
、android:propertyYName=""
等屬性,這些屬性的作用就是聲明屬性的名稱。
ObjectAnimator 對 ValueAnimator 進行了封裝,一方面在創建對象時綁定了屬性和目標對象,另一方面通過 Interpolator 返回當前的進度,再經過 Evaluator 根據進度計算出具體的值,最后根據屬性拼接 set 函數并反射調用,并將當前值作為參數傳入,實現動畫,不必在監聽器中監聽動畫進度。
代碼創建對象
public static ObjectAnimator ofInt(Object target, String propertyName, int... values)
public static ObjectAnimator ofInt(Object target, String xPropertyName, String yPropertyName,Path path)
public static ObjectAnimator ofArgb(Object target, String propertyName, int... values)
public static <T> ObjectAnimator ofArgb(T target, Property<T, Integer> property,int... values)
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
public static ObjectAnimator ofFloat(Object target, String xPropertyName, String yPropertyName,Path path)
public static ObjectAnimator ofObject(Object target, String propertyName,TypeEvaluator evaluator, Object... values)
public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)
ofXXX 方法內部創建了 ObjectAnimator 對象,并調用了 setXXXValues 方法,類似于 ValueAnimator,最終都是調用了 setValues 方法,在方法中給成員變量 PropertyVaulesHolder[] mValues
賦值。
ofPropertyValuesHolder 可以同時操作多個屬性。
5、AnimatorSet
xml 文件定義
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially|together"
>
</set>
通過 set
標簽定義,android:ordering
屬性表示動畫是按順序執行還是同時執行。
public 方法
public AnimatorSet()
public void setTarget(Object target)
public void setInterpolator(TimeInterpolator interpolator)
public void playTogether(Animator... items)
public void playTogether(Collection<Animator> items)
public void playSequentially(Animator... items)
public void playSequentially(List<Animator> items)
public Builder play(Animator anim)
public void cancel()
public void end()
AnimatorSet 使用了建造者模式,內部定義了一個 Builder 類
public class Builder {
private Node mCurrentNode;
Builder(Animator anim) {
mDependencyDirty = true;
mCurrentNode = getNodeForAnimation(anim);
}
public Builder with(Animator anim) {
Node node = getNodeForAnimation(anim);
mCurrentNode.addSibling(node);
return this;
}
public Builder before(Animator anim) {
mReversible = false;
Node node = getNodeForAnimation(anim);
mCurrentNode.addChild(node);
return this;
}
public Builder after(Animator anim) {
mReversible = false;
Node node = getNodeForAnimation(anim);
mCurrentNode.addParent(node);
return this;
}
public Builder after(long delay) {
// setup dummy ValueAnimator just to run the clock
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
anim.setDuration(delay);
after(anim);
return this;
}
}
Builder 類定義了四個方法來設置動畫的執行順序,當屬性動畫順序執行或指定動畫執行順序時,直接或間接調用 play 方法返回 Builder 對象控制動畫的執行順序。
監聽器
AnimatorSet 內部也定義了監聽器 AnimatorSetListener,類似于 Animator.AnimatorListener 監聽動畫開始、結束、取消、重復。
6、包裝類
ObjectAnimtor 操作的屬性必須要有 setXXX 方法,如果動畫的時候沒有傳遞初始值,還要有 getXXX 方法
針對上述情況,官方文檔給出了三種解決方法:
- 給你的對象加上 get 和 set 方法,如果你有權限的話;
- 用一個類來包裝原始對象,間接為其提供 get 和 set 方法;
這個時候目標對象就變成了包裝類的對象,而原始對象成為包裝類的一個成員變量,定義 set 和 get 方法設置或獲取原始對象的屬性值。 - 采用 ValueAnimator,監聽動畫過程,自己實現屬性改變;
7、插值器 Interpolator
TimeInterpolator 中文翻譯為時間插值器,它的作用是根據時間百分比來計算當前屬性值改變的百分比,在 android.view.animation 包下面定義了 TimeInterpolator 的子接口 Interpolator,并且已經定義了十幾個實現類:
在 Interpolator 的實現類里面都有一個
public float getInterpolation(float input)
方法,這個方法的參數代表動畫執行時間進度的百分比,取值范圍是0-1,0代表起點,1代表終點,隨著動畫的播放,input 從0到1逐漸變大;返回值是當前時間點對應的屬性值改變的百分比,這個可以為負值,也可以大于1,為負值表示屬性值小于起始值,大于1表示屬性值超過終點值;
1.AccelerateInterpolator 加速插值器
該類有一個成員變量 mFractor 決定了加速的快慢
2. DecelerateInterpolator 減速插值器
3. AccelerateDecelerateInterpolator 加速減速插值器
4. LinearInterpolator 線性插值器
5. BounceInterpolator 彈跳插值器
6.AnticipateInterpolator 回蕩秋千插值器
該類有一個成員變量 mTension 決定回蕩幅度的大小
7. AnticipateOvershootInterpolator
8. CycleInterpolator 正弦周期變化插值器
9. OvershootInterpolator
通過上面的圖像可以看出,圖形的曲線表示的是屬性值的變化的百分比,0表示屬性起始值,1表示屬性結束值,屬性值主要在0~1之間變化,也可以超出該范圍,曲線的斜率可以表示變化的速率
8、估值器 TypeEvaluator
插值器返回的只是屬性值變化的百分比,還需要使用估值器映射出真正的屬性值。
TypeEvaluator 中之定義了一個方法 evaluate ,三個參數分別為 Interpolator 返回的因子,屬性的起始值和結束值。
系統中已經定義了幾種實現類
看 IntEvaluator 類,evaluate 方法的返回值為**初始值 + 百分比 * (結束值 - 初始值)
各種 Evaluator 實現類的區別就在于屬性值的類型的不同,有時候需要自定義 TypeEvaluator