文章主要內容來源《Android開發藝術探索》,部份內容來源網上的文章,文中會有連接。android
Android系統提供了兩個動畫框架:屬性動畫框架和View動畫框架。 兩個動畫框架都是可行的選項,可是屬性動畫框架一般是首選的使用方法,由於它更靈活,並提供更多的功能。 除了這兩個框架,還可使用Drawable動畫(即逐幀動畫,AnimationDrawable),它容許你加載Drawable資源並逐幀地顯示它們。算法
View動畫框架(補間動畫)
View動畫框架中一共提供了AlphaAnimation(透明度動畫)、RotateAnimation(旋轉動畫)、ScaleAnimation(縮放動畫)、TranslateAnimation(平移動畫)四種類型的補間動畫;而且View動畫框架還提供了動畫集合類(AnimationSet),經過動畫集合類(AnimationSet)能夠將多個補間動畫以組合的形式顯示出來。補間動畫的實現,通常會採用xml文件的形式,那樣代碼會更容易書寫和閱讀,同時也更容易複用。框架屬性動畫框架
與屬性動畫相比View動畫存在一個缺陷,View動畫改變的只是View的顯示,而沒有改變View的響應區域,而且View動畫只能對View作四種類型的補間動畫。所以Google在Android3.0(API級別11)及其後續版本中添加了屬性動畫框架,從名稱中就能夠知道只要某個類具備屬性(即該類含有某個字段的set和get方法),那麼屬性動畫框架就能夠對該類的對象進行動畫操做(其實就是經過反射技術來獲取和執行屬性的get,set方法),一樣屬性動畫框架還提供了動畫集合類(AnimatorSet),經過動畫集合類(AnimatorSet)能夠將多個屬性動畫以組合的形式顯示出來。dom做者:ForeverCy
連接:http://www.jianshu.com/p/b117c974deaf
來源:簡書
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。ide
View動畫的四種變換效果對應着Animation的四個子類:TranslateAnimation、ScaleAnimation、RotateAnimation、AlphaAnimation。四種動畫能夠用這四個類經過代碼實現,也可使用XML文件來定義。建議使用XML來定義動畫,由於XML格式可讀性好並且方便複用。oop
名稱 | 標籤 | 子類 |
---|---|---|
平移動畫 |
|
TranslateAnimation |
縮放動畫 |
|
ScaleAnimation |
選中動畫 |
|
RotateAnimation |
透明度動畫 |
|
AlphaAnimation |
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="" android:shareInterpolator="true|false"> <translate android:fromXDelta="" android:toXDelta="" android:fromYDelta="" android:toYDelta="" /> <scale android:fromXScale="" android:toXScale="" android:fromYScale="" android:toYScale="" android:pivotX="" android:pivotY="" /> <rotate android:fromDegrees="" android:toDegrees="" android:pivotX="" android:pivotY="" /> <alpha android:fromAlpha="" android:toAlpha="" /> <set> <!--set嵌套set--> </set> </set>
View動畫能夠是單個動畫,也能夠由一系列動畫組成,使用
android:interpolator表示動畫集合所使用的插值器,插值器影響動畫的速度,好比非勻速動畫就須要經過插值器來控制動畫的播放過程。這個屬性能夠不指定,默認是@android:anim/accelerate_decelerate_interpolator,即加速減速插值器。
android:shareInterpolator表示集合中的動畫是否和集合共享同一個插值器。若是集合不指定插值器,那麼子動畫就須要單獨指定所須要的插值器或者使用默認值。lua
android:fromXDelta x的起始值
android:toXDelta x的結束值
android:fromYDelta y的起始值
android:toYDelta y的結束值.net
android:fromXScale 水平方向縮放的起始值
android:toXScale 水平方向縮放的結束值
android:fromYScale 豎直方向縮放的起始值
android:toYScale 豎直方向縮放的結束值
android:pivotX 縮放的軸點的x座標
android:pivotY 縮放的軸點的y座標線程
android:fromDegrees 旋轉開始的角度
android:toDegrees 旋轉結束的角度
android:pivotX 旋轉的軸點的x座標
android:pivotY 選中的軸點的y座標
android:fromAlpha 透明度的起始值
android:toAlpha 透明度的結束值
android:duration 動畫的持續時間
android:fillBefore 動畫結束後是否回到執行前的位置
android:fillAfter 動畫結束後是否停留在結束位置
android:interpolator 動畫使用的插值器
android:startOffset 動畫執行以前的等待時間
android:repeatCount 動畫重複執行的次數
xml屬性都有對應的set方法
首先編寫動畫xml文件test_anim.xml
Button mButton = (Button)findViewById(R.id.button); Animation animation = AnimationUtils.loadAnimation(context, R.anim.test_anim); mButton.startAnimation(animation);
也能夠經過代碼實現
AlphaAnimation animation = new AlphaAnimation(0, 1); animation.setDuration(300); mButton.startAnimation(animation);
使用setAnimationListener方法能夠給動畫添加過程監聽。
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:delay="150" android:animationOrder="normal" android:animation="@anim/anim_item"/>
android:delay 子元素開始動畫的時間延遲
android:animationOrder 子元素動畫的順序。有normal(順序)、reverse(逆向)、random(隨機)三種順序。
android:animation 子元素入場的具體動畫
<translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromXDelta="500" android:toXDelta="0"/>
<ListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:layoutAnimation="@anim/anim_layout" />
除了經過xml中指定layoutAnimation屬性,也能夠經過LayoutAnimationController來實現:
Animation animation = AnimationUtils.loadAnimation(context, R.anim.anim_item); LayoutAnimationController controller = new LayoutAnimationController(animation); controller.setDelay(0.5f); controller.setOrder(LayoutAnimationController.ORDER_NORMAL); listView.setLayoutAnimation(controller);
使用overridePendingTransition(int enterAnim, int exitAnim)方法實現Activity的切換動畫,這個方法必須在startActivity()或者finish()以後調用才能生效。
Fragment也能夠添加切換動畫,經過FragmentTransaction中的setCustomAnimations()方法實現。
幀動畫的標籤是
示例代碼
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/img1" android:duration="500"/> <item android:drawable="@drawable/img2" android:duration="500"/> <item android:drawable="@drawable/img3" android:duration="500"/> </animation-list>
Button mButton = (Button)findViewById(R.id.button1); mButton.setBackgroundResource(R.drawable.frame_animation); AnimationDrawable drawable = (AnimationDrawable)mButton.getBackground(); drawable.start();
注意幀動畫容易引發OOM。
屬性動畫從 API 11 纔有,屬性動畫能夠對任意對象的屬性進行動畫而不只僅是View,達到的效果是:在一個時間間隔內完成對象從一個屬性值到另外一個屬性值的改變。屬性動畫經常使用的動畫類:ValueAnimator、ObjectAnimator、AnimatorSet。ObjectAnimator繼承自ValueAnimator,AnimatorSet是動畫集合。
屬性動畫也有對應的xml標籤,可是建議使用代碼來實現屬性動畫,由於使用代碼比xml簡單。並且不少時候一個屬性的起始值沒法提早肯定。
ObjectAnimator.ofFloat(myObject, "translationY", -myObject.getHeight()).start();
ValueAnimator anim = ObjectAnimator.ofInt(myObject, "backgroundColor",0xFFFF8080,0xFF8080FF); anim.setDuration(3000); anim.setEvaluator(new ArgbEvaluator()); anim.setRepeatCount(ValueAnimator.INFINITE); anim.setRepeatMode(ValueAnimator.REVERSE); anim.start();
AnimatorSet set = new AnimatorSet(); set.playTogether( ObjectAnimator.ofFloat(myView, "rotationX", 0, 360), ObjectAnimator.ofFloat(myView, "rotationY", 0, 180), ObjectAnimator.ofFloat(myView, "rotation", 0, -90), ObjectAnimator.ofFloat(myView, "translationX", 0, 90), ObjectAnimator.ofFloat(myView, "translationY", 0, 90), ObjectAnimator.ofFloat(myView, "scaleX", 1, 1.5f), ObjectAnimator.ofFloat(myView, "scaleY", 1, 0.5f), ObjectAnimator.ofFloat(myView, "alpha", 1, 0.25f, 1) ); set.setDuration(5*1000).start();
上面代碼用到一個主要的方法
ObjectAnimator.ofFloat(target, propertyName, values...);
target 是動畫目標,任何對象,不必定必須是View
propertyName 是屬性名字
values 是可變參數, 從v1變化到v2到vn。。。
例子:
mIv是一個imageView
//alpha 從0 到1 的動畫
ObjectAnimator.ofFloat(mIv, "alpha", 0f,1f)
.setDuration(500)
.start();
若是要實現其餘效果,修改propertyName和values就好了。
屬性動畫的原理就是經過反射,以動畫的效果屢次調用set方法來改變屬性值的。因此,使用屬性動畫時,相應的對象屬性必須有set方法,get方法能夠沒有,可是若是使用動畫的時候沒有傳遞初始值,就必須提供get方法,由於系統要經過get方法獲取屬性的默認初始值。
alpha 透明度
rotation z軸旋轉
rotationX x軸旋轉
rotationY y軸旋轉
translationX x水平偏移
translationY y水平偏移
ScaleX x軸縮放
ScaleY y軸縮放
插值器(TimeInterpolator/Interpolator)用來修飾動畫效果,定義動畫的變化規率(變化趨勢),好比平移動畫,能夠勻速平移也能夠加速平移,這個由插值器決定。
估值器(Evaluator)用來決定具體的數值變化,好比(勻)加速平移時,「加速度」是多少由估值器決定。
插值器TimeInterpolator和Interpolator,後者是繼承前者的接口。
TimeInterpolator接口是屬性動畫中新增的,用於兼容Interpolator接口,這使得全部過去的Interpolator實現類均可以直接在屬性動畫使用。
出自:http://blog.csdn.net/carson_ho/article/details/72863901
IntEvaluator 以整型的形式從初始值到結束值 進行過渡
FloatEvaluator 以浮點型的形式從初始值到結束值 進行過渡
ArgbEvaluator 以Argb類型的形式從初始值到結束值 進行過渡
若是系統內置的插值器和估值器沒法知足需求,也能夠自定義。
View動畫的插值器實現Interpolator接口,View動畫沒有估值器
屬性動畫的插值器實現實現TimeInterpolator接口,估值器實現TypeEvaluator接口
自定義插值器和估值器參考系統內置的插值器和估值器便可。
如下摘自http://blog.csdn.net/carson_ho/article/details/72863901
實現Interpolator接口自定義插值器的說明(TimeInterpolator接口相同)
public interface Interpolator { // 內部只有一個方法 float getInterpolation(float input) { // 參數說明 // input值值變化範圍是0-1,且隨着動畫進度(0% - 100% )均勻變化 // 即動畫開始時,input值 = 0;動畫結束時input = 1 // 而中間的值則是隨着動畫的進度(0% - 100%)在0到1之間均勻增長 ...// 插值器的計算邏輯 return xxx; // 返回的值就是用於估值器繼續計算的fraction值 } }
實現TypeEvaluator接口自定義估值器的說明
public interface TypeEvaluator { public Object evaluate(float fraction, Object startValue, Object endValue) { // 參數說明 // fraction:插值器getInterpolation()的返回值 // startValue:動畫的初始值 // endValue:動畫的結束值 ....// 估值器的計算邏輯 return xxx; // 賦給動畫屬性的具體數值 // 使用反射機制改變屬性變化 // 特別注意 // 插值器的input值 和 估值器fraction有什麼關係呢? // 答:input的值決定了fraction的值:input值通過計算後傳入到插值器的getInterpolation() // 而後經過實現getInterpolation()中的邏輯算法,根據input值來計算出一個返回值,而這個返回值就是fraction了 } }
View動畫和屬性動畫均可以使用插值器,估值器只有屬性動畫能夠用。
插值器用法
// 步驟1:建立須要設置動畫的視圖View Button mButton = (Button) findViewById(R.id.Button); // 步驟2:建立透明度動畫的對象 & 設置動畫效果 Animation alphaAnimation = new AlphaAnimation(1,0); alphaAnimation.setDuration(3000); // 步驟3:建立對應的插值器類對象 Interpolator overshootInterpolator = new OvershootInterpolator(); // 步驟4:給動畫設置插值器 alphaAnimation.setInterpolator(overshootInterpolator); // 步驟5:播放動畫 mButton.startAnimation(alphaAnimation);
估值器用法
// 在第3個參數中傳入對應估值器類的對象 ObjectAnimator anim = ObjectAnimator.ofObject(myView2, "height", new Evaluator(),1,3);
有兩個監聽接口AnimatorListener和AnimatorUpdateListener。AnimatorListener和View動畫的AnimationListener相似,能夠監聽動畫的開始、結束等過程。AnimatorUpdateListener能夠監聽動畫的每一幀變化,動畫每變化一幀,接口裏的方法被調用一次。
private void performAnimate(final View button, final int start, final int end) { ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { //持有一個IntEvaluator對象,方便下面估值的時候使用 private IntEvaluator mIntEvaluator = new IntEvaluator(); @Override public void onAnimationUpdate(ValueAnimator animator) { //得到當前動畫的進度值,整型1-100之間 int currentValue = (int) animator.getAnimatedValue(); //得到當前進度佔整個動畫過程的比例,浮點型,0-1之間 float fraction = animator.getAnimatedFraction(); //直接調用整型估值器,經過比例計算出寬度,而後設給Button button.getLayoutParams().width = mIntEvaluator.evaluate(fraction, start, end); button.requestLayout(); } }); valueAnimator.setDuration(5000).start(); } @Override public void onClick(View v) { if (v == mButton) { performAnimate(mButton, mButton.getWidth(), 500); } }
View動畫能夠設置ViewGroup的子View的出場動畫,屬性動畫能夠爲ViewGroup的子View的顯示和隱藏設置過渡動畫。出場動畫文中已經介紹,屬性動畫實現的過分動畫詳細見ForeverCy的文章Android中的View動畫和屬性動畫 中的相關部分。