Android動畫淺析,android淺析

來源:互聯網
上載者:User

Android動畫淺析,android淺析
前言

在應用的開發中,動畫是必不可少的一部分,否則很多視覺效果會顯得特別突兀。今天我們就來瞭解一下Android中的動畫庫。


View中實現動畫的過程

View的alpha動畫直接通過setAlpha(float al)函數來修改透明度實現,縮放、平移、旋轉等都是通過圖形矩陣變換來實現。圖形變換是圖形學中基本知識,簡單來說就是,每種變換都是一次矩陣運算。在Android中,Canvas類包含當前矩陣,當前調用Canvas.drawBitmap(bm,x,y,Paint)繪製時,android會先把bmp做一次矩陣運算,然後將運算結果顯示在Canvas上。這樣編程人員只需不斷修改Canvas的矩陣並重新整理螢幕,View裡對象就會不停的做圖形變換,動畫就形成了。

    View設定動畫,設定動畫屬性,在動畫啟動時,會調用invalidate方法重繪View。從而觸發onDraw函數;在onDraw函數中,調用動畫的getTransformation方法,得到目前時間點的矩陣,getTransformation函數又會調用動畫的applyTransformation函數,applyTransformation函數通過一個計算因子 (由插值器通過動畫執行的百分比計算出來的因子)來計算當前時刻View屬性的值,修改View的屬性達到圖形變換。View會判斷getTransformation的傳回值,若為真,說明動畫未完成,調用invalidate方法重新整理螢幕,重繪View,從而進入下一幀動畫,再次執行上述過程;若為假,說明動畫完成。


動畫的分類Android平台為我們提供了兩類動畫,Tween(補間動畫)動畫和Frame(幀)動畫。Tween動畫是通過對情境中的對象不斷進行映像變換(平移、縮放、旋轉等)來產生動畫效果的;Frame動畫則是順序播放事先做好的每幀映像,類似於快速的投影片一樣。補間動畫Tween動畫是通過預先定義一個動畫,這個動畫指定了圖形變換的類型(旋轉、平移、縮放等)、啟動時間、期間、起始值,在View繪製時就會沿著時間軸修改這些屬性值,從而達到動畫效果。動畫可以通過代碼定義,也可以通過xml來定義。如果動畫是在xml中定義的,那麼使用AnimationUtils.loadAnimation(context, R.anim.your_anim);來載入即可。 Alpha:透明度動畫該動畫是在指定的時間段內修改View的透明度,從0.3到1.0f的透明度動畫樣本如下 : 代碼定義動畫 :
  AlphaAnimation alphaAnimation = new AlphaAnimation(0.3f, 1.0f) ;        alphaAnimation.setDuration(1000);
xml 定義動畫:
<?xml version="1.0" encoding="utf-8"?>      <!-- 透明度 -->      <alpha  xmlns:android="http://schemas.android.com/apk/res/android"        android:fromAlpha="1"          android:toAlpha="0"           android:duration="1000"          />  
然後執行通過view的setAnimation或者startAnimation設定動畫即可。
Scale:縮放動畫對view的縮放動畫,需要指定x, y軸上各自的縮放值。樣本為在一秒中之內把View縮放為原來的一半大小,縮放的中心點為view的中心。代碼定義動畫:
        ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 0.5f, 1.0f, 0.5f,0.5f, 0.5f);        scaleAnimation.setDuration(1000);
xml 定義動畫: 
<?xml version="1.0" encoding="utf-8"?>       <!-- 縮放 -->      <scale  xmlns:android="http://schemas.android.com/apk/res/android"        android:fromXScale="1"           android:fromYScale="1"           android:toXScale="0.5"           android:toYScale="0.5"           android:pivotX="0.5"          android:pivotY="0.5"          android:duration="3000"           /> 

Translate:位移動畫位移動畫是將View從一個點移動到某一個點的動畫。例如將view在一秒鐘內從(0,0)位置移動到(100, 100)位置。代碼定義:
        TranslateAnimation translateAnimation = new TranslateAnimation(0, 100, 0, 100) ;        translateAnimation.setDuration(1000);

XML定義動畫 :
<?xml version="1.0" encoding="utf-8"?> <!-- 移動 -->      <translate   xmlns:android="http://schemas.android.com/apk/res/android"        android:fromXDelta="0"          android:fromYDelta="0"          android:toXDelta="100"          android:toYDelta="100"           android:duration="000"           />  
Rotate:旋轉動畫旋轉動畫負責對view的角度進行調整,例如將view從當前角度旋轉360度。代碼定義:
  RotateAnimation rotateAnimation = new RotateAnimation(0, 360) ;        rotateAnimation.setDuration(1000);
XML定義:
<?xml version="1.0" encoding="utf-8"?>      <!-- 旋轉 -->      <rotate  xmlns:android="http://schemas.android.com/apk/res/android"        android:fromDegrees="0"          android:toDegrees="360"          android:pivotX="50%"          android:pivotY="50%"           android:duration="1000"           /> 


幀動畫

幀動畫可以想象為一部很短的電影,他由數量有限的主要畫面格組成,當這個幀動畫時這些主要畫面格快速的切換,從而達到動畫的效果。

<?xml version="1.0" encoding="utf-8"?><animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">    <item android:drawable="@drawable/p1" android:duration="200" />    <item android:drawable="@drawable/p2" android:duration="200" />    <item android:drawable="@drawable/p3" android:duration="200" />    <item android:drawable="@drawable/p4" android:duration="200" />    <item android:drawable="@drawable/p5" android:duration="200" />    <item android:drawable="@drawable/p6" android:duration="200" />    <item android:drawable="@drawable/p7" android:duration="800" />    <item android:drawable="@drawable/p8" android:duration="200" />    <item android:drawable="@drawable/p9" android:duration="200" />    <item android:drawable="@drawable/p10" android:duration="200" />    <item android:drawable="@drawable/p11" android:duration="200" /></animation-list>
使用幀動畫與補間動畫不太一樣,樣本如下 : 

 // 通過逐幀動畫的資源檔獲得AnimationDrawable樣本    AnimationDrawable frameAnim = (AnimationDrawable) getResources().getDrawable(R.drawable.my_frame_anim);// 把AnimationDrawable設定為myView的背景myView.setBackgroundDrawable(frameAnim);

動畫的插值器(Interpolator)

在補間動畫中,我們一般只定義首幀和尾幀,然後由系統自動產生中間幀,產生中間幀的這個過程可以成為“插值”。插值器的作用是告訴動畫某個屬性(比如顏色的漸層)如何隨時間變化 ,在duration周期內每個時刻對應的屬性值。下面是幾種常見的插值器:


android 系統預設支援AccelerateDecelerateInterpolator 、 AccelerateInterpolator 、 AnticipateInterpolator 、AnticipateOverShootInterpolator 、 BounceInterpolator 、 CycleInterpolator 、DecelerateInerpolator 、 LinearInterpolator 、 OverShootInterpolator 共 9 種插值器(若這些插值器不能滿足需求,則可以自訂插值器)。

例如,一個alpha動畫在一秒內從0.0f到1.0f變換,線性插值器的動畫為勻速執行的。但是加速插值器的動畫會隨著時間的增加而越來越快。

插值器通過getInterpolation方法獲得插值因子,插值因子的計算也在此函數中完成。例如線性插值器,它的動畫則是勻速運動的,因此在它的getInterpolation函數中插值因子只跟時間相關,與其他因素無關。getInterpolation(int inpput)函數中的參數即動畫執行的百分比,也可以認為是動畫已經執行時間和動畫周期的百分比。該值為0.0f 到 1.0f,即動畫的開始到結束。

/** * An interpolator where the rate of change is constant * */public class LinearInterpolator implements Interpolator {    public LinearInterpolator() {    }        public LinearInterpolator(Context context, AttributeSet attrs) {    }        public float getInterpolation(float input) {        return input;    }}
再看加速插值器,即動畫的速度會隨著時間的推移而越來越快。我們看看它的getInterpolation實現:

    public float getInterpolation(float input) {        if (mFactor == 1.0f) {            return input * input;        } else {            return (float)Math.pow(input, mDoubleFactor);        }    }
預設情況下mFactor會為1.0f, 隨著動畫的執行,input慢慢增大,getInterpolation函數返回的數值的大小變化範圍會越來越大,從而導致動畫變快。

使用矩陣Matrix自訂動畫

自訂動畫時,我們主要就是覆寫applyTransformation(float interpolatedTime, Transformation t) 方法,在方法是在動畫執行時就是調用該方法來實現動畫操作,我們在這裡需要實現修改alpha, 縮放,平移等動畫。interpolatedTime是由插值器計算出來的因子,由動畫的執行百分比與插值器的策略計算而來,值為0.0f 到 1.0f。參數t為矩陣變換的封裝類。在這裡我們只討論使用矩陣實現的自訂動畫。例如,我們需要定製一個動畫,是它能夠在低於API 11 版本的系統裡實現Y軸的旋轉動畫,android中的RorateAnimation動畫只支援在Z軸上的旋轉動畫,這是我們就可以通過矩陣來實現。關於矩陣的資料,請移步,Android中映像變換Matrix的原理、代碼驗證和應用(一),Android Matrix理論與應用詳解,Android--Matrix圖片變換處理。


/** * @author mrsimple */public class RotateYAnimation extends Animation {    private int halfWidth;    private int halfHeight;    // 使用Camera實現3D旋轉    Camera mCamera = new Camera();    //     protected float mRotateY = 0.0f;    /**     * width,height為執行該動畫的view的寬度、高度。後面兩個參數為執行該動畫的view的parent的寬度、高度     */    @Override    public void initialize(int width, int height, int parentWidth,            int parentHeight) {        super.initialize(width, height, parentWidth, parentHeight);        setDuration(2000);        setFillAfter(true);        halfWidth = width / 2;        halfHeight = height / 2;        setInterpolator(new LinearInterpolator());    }    // 設定旋轉角度    public void setRotateY(float rorateY) {        mRotateY = rorateY;    }    @Override    protected void applyTransformation(float interpolatedTime, Transformation t) {        final Matrix matrix = t.getMatrix();        mCamera.save();        // 使用Camera設定旋轉的角度        mCamera.rotateY(mRotateY * interpolatedTime);        // 將旋轉變換應用到matrix上        mCamera.getMatrix(matrix);        mCamera.restore();                // 在變換前,將動畫的中心點從預設的(0,0)移動(0, -halfHeight)        matrix.preTranslate(0, -halfHeight);        // 變換後再從(-halfWidth, -halfHeight)移動halfWidth,halfHeight,使之再次回到(0,0)        matrix.postTranslate(0, halfHeight);        // View view;    }}

使用代碼 : 

               Button btn = new Button(MainActivity.this) ;                btn.setText("RotateY");                MyAnimation animation = new MyAnimation();                animation.setRotateY(45f);                animation.setDuration(2000);// 啟動動畫                btn.startAnimation(animation);  
效果  (中的view並不是button,是我另外例子中的view): 




android View設定隱藏動畫問題

mAppHiddenAction.setDuration(400);
mAppGridView.startAnimation(mHiddenAction);
scrollView.startAnimation(mAppHiddenAction);
relativelayout.startAnimation(mAppHiddenAction);

後面這些代碼應該在mAppHiddenAction結束後再執行,而不是直接在這就執行,你可用hander+定時器延後執行即可
scrollView.setVisibility(View.GONE);
mAppGridView.setVisibility(View.GONE);
tv.setVisibility(View.GONE);
btn_save.setVisibility(View.GONE);
 
android 動畫效果

xml中設定fillAfter=true
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.