本系列文章主要介紹了OPhone 2.0 SDK提供的兩種實現2D動畫的方式:幀動畫和補間動畫。文章的每個知識點都提供了精彩的實例以向讀者展示2D動畫的具體實現方法。通過對本系列文章的學習,讀者可利用2D動畫實現非常絢麗的界面效果。
相關閱讀:
基於OPhone 2.0的2D動畫實踐(一) http://www.linuxidc.com/Linux/2011-11/48125.htm
基於OPhone 2.0的2D動畫實踐(二) http://www.linuxidc.com/Linux/2011-11/48124.htm
基於OPhone 2.0的2D動畫實踐(三) http://www.linuxidc.com/Linux/2011-11/48126.htm
補間動畫簡介
如果動畫中的圖像變換比較有規律時,可以采用自動生成中間圖像的方式來生成動畫。例如,圖像的移動、旋轉、縮放等。當然,還有更復雜的情況,例如,由正方形變成圓形、圓形變成橢圓形,這些變化過程中的圖像都可以根據一定的數學算法自動生成。而我們只需要指定動畫的第1幀和最後一幀的圖像即可。這種自動生成中間圖像的動畫被稱為補間(Tween)動畫。
補間動畫的優點是節省硬盤空間。這是因為這種動畫只需要提供兩幀圖像(第1幀和最後一幀),其他的圖像都由系統自動生成。當然,這種動畫也有一定的缺點,就是動畫很復雜時無法自動生成中間圖像,例如,由電影畫面組件的動畫,由於每幅畫面過於復雜,系統無法預料下一幅畫面是什麼樣子。因此,這種復雜的動畫只能使用幀動畫來完成。在本節將介紹OPhone SDK提供的4種補間動畫效果:移動、縮放、旋轉和透明度。OPhone SDK並未提供更復雜的補間動畫。如果要實現更復雜的補間動畫,需要開發人員自已編碼來完成。
移動補間動畫
移動是最常見的動畫效果。我們可以通過配置動畫文件(xml文件)或Java代碼來實現補間動畫的移動效果。補間動畫文件需要放在res\anim目錄中。在動畫文件中通過<translate>標簽設置移動效果。假設在res\anim目錄下有一個動畫文件:test.xml,該文件的內容如下:
- <translate xmlns:Android="http://schemas.android.com/apk/res/android"
- android:interpolator="@android:anim/accelerate_interpolator"
- android:fromXDelta="0" android:toXDelta="320" android:fromYDelta="0"
- android:toYDelta="0" android:duration="2000" />
從上面的配置代碼可以看出,<translate>標簽中設置了6個屬性,這6個屬性的含義如下:
android:interpolator:表示動畫渲染器。通過android:interpolator屬性可以設置3個動畫渲染器:accelerate_interpolator(動畫加速器)、decelerate_interpolator(動畫減速器)和accelerate_decelerate_interpolator(動畫加速減速器)。動畫加速器使動畫在開始時速度最慢,然後逐漸加速。動畫減速器使動畫在開始時速度最快,然後逐漸減速。動畫加速減速器使動畫在開始和結束時速度最慢,但在前半部分時開始加速,在後半部分時開始減速。
android:fromXDelta:動畫起始位置的橫坐標。
android:toXDelta:動畫結束位置的橫坐標。
android:fromXDelta:動畫起始位置的縱坐標。
android:toYDelta:動畫結束位置的縱坐標。
android:duration:動畫的持續時間。單位是毫秒。也就是說,動畫要在android:duration屬性指定的時間內從起始點移動到結束點。
裝載補間動畫文件需要使用android.view.animation.AnimationUtils. loadAnimation方法,該方法的定義如下:
- public static Animation loadAnimation(Context context, int id);
其中id表示動畫文件的資源ID。裝載test.xml文件的代碼如下:
- Animation animation = AnimationUtils.loadAnimation(this, R.anim.test);
假設有一個EditText組件(editText),將test.xml文件中設置的補間動畫應用到EditText組件上的方式有如下兩種:
1. 使用EditText類的startAnimation方法,代碼如下:
- editText.startAnimation(animation);
2. 使用Animation類的start方法,代碼如下:
- // 綁定補間動畫
- editText.setAnimation(animation);
- // 開始動畫
- animation.start();
使用上面兩種方式開始補間動畫都只顯示一次。如果想循環顯示動畫,需要使用如下的代碼將動畫設置成循環狀態。
- animation.setRepeatCount(Animation.INFINITE);
上面兩行代碼在開始動畫之前和之後執行都沒有問題。
移動補間動畫的實例
本例的動畫效果是在屏幕上方的EditText組件從左到右循環勻速水平移動。EditText下方的小球上下移動。從上到下移動時加速。從下到上移動時減速。
本例涉及到3個動畫渲染器:accelerate_interpolator、decelerate_interpolator和linear_interpolator。其中前兩個動畫渲染器可以直接作為android:interpolator屬性的值,而linear_interpolator雖然在系統中已定義,但由於不是public的,因此,需要自己定義linear_interpolator.xml文件。當然,也可以將系統的linear_interpolator.xml文件復制到Eclipse工程中的res\anim目錄下。
在本例中定義了3個動畫文件,其中translate_right.xml被應用於EditText組件。translate_bottom.xml(從上到下移動,加速)和translate_top.xml(從下到上移動,減速)被應用於小球(ImageView組件)。這3個動畫文件的內容如下:
- translate_right.xml
- <translate xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@anim/linear_interpolator"
- android:fromXDelta="-320" android:toXDelta="320" android:fromYDelta="0"
- android:toYDelta="0" android:duration="5000" />
-
- translate_bottom.xml
- <translate xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@android:anim/accelerate_interpolator"
- android:fromXDelta="0" android:toXDelta="0" android:fromYDelta="0"
- android:toYDelta="260" android:duration="2000" />
- translate_top.xml
- <translate xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@android:anim/decelerate_interpolator"
- android:fromXDelta="0" android:toXDelta="0" android:fromYDelta="260"
- android:toYDelta="0" android:duration="2000" />
EditText組件的循環水平移動可以直接使用setRepeatMode和setRepeatCount方法進行設置。而小球的移動需要應用兩個動畫文件。本例采用的方法是在一個動畫播放完後,再將另一個動畫文件應用到顯示小球的ImageView組件中。這個操作需要在AnimationListener接口的onAnimationEnd方法中完成。
運行本例後,單擊【開始動畫】按鈕後,EditText組件從屏幕的左側出來,循環水平向右移動,當EditText組件完全移進屏幕右側時,會再次從屏幕左側出來。同時小球會上下移動。效果如圖1所示。
圖1 移動補間動畫
本例的完整代碼如下:
- package net.blogjava.mobile;
-
- import android.app.Activity;
- import android.os.Bundle;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.animation.Animation;
- import android.view.animation.AnimationUtils;
- import android.view.animation.Animation.AnimationListener;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.ImageView;
-
- public class Main extends Activity implements OnClickListener, AnimationListener
- {
- private EditText editText;
- private ImageView imageView;
- private Animation animationRight;
- private Animation animationBottom;
- private Animation animationTop;
-
- // animation參數表示當前應用到組件上的Animation對象
- @Override
- public void onAnimationEnd(Animation animation)
- {
- // 根據當前顯示的動畫決定下次顯示哪一個動畫
- if (animation.hashCode() == animationBottom.hashCode())
- imageView.startAnimation(animationTop);
- else if (animation.hashCode() == animationTop.hashCode())
- imageView.startAnimation(animationBottom);
- }
- @Override
- public void onAnimationRepeat(Animation animation)
- {
- }
- @Override
- public void onAnimationStart(Animation animation)
- {
- }
- @Override
- public void onClick(View view)
- {
- // 開始EditText的動畫
- editText.setAnimation(animationRight);
- animationRight.start();
- animationRight.setRepeatCount(Animation.INFINITE);
- editText.setVisibility(EditText.VISIBLE);
- // 開始小球的動畫
- imageView.startAnimation(animationBottom);
- }
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- editText = (EditText) findViewById(R.id.edittext);
- editText.setVisibility(EditText.INVISIBLE);
- Button button = (Button) findViewById(R.id.button);
- button.setOnClickListener(this);
- imageView = (ImageView) findViewById(R.id.imageview);
- animationRight = AnimationUtils.loadAnimation(this,R.anim.translate_right);
- animationBottom = AnimationUtils.loadAnimation(this,R.anim.translate_bottom);
- animationTop = AnimationUtils.loadAnimation(this, R.anim.translate_top);
- animationBottom.setAnimationListener(this);
- animationTop.setAnimationListener(this);
- }
- }
縮放補間動畫
通過<scale>標簽可以定義縮放補間動畫。下面的代碼定義了一個標准的縮��補間動畫。
- <scale xmlns:android="http://schemas.android.com/apk/res/android"
- android:interpolator="@android:anim/decelerate_interpolator"
- android:fromXScale="0.2" android:toXScale="1.0" android:fromYScale="0.2"
- android:toYScale="1.0" android:pivotX="50%" android:pivotY="50%"
- android:duration="2000" />
<scale>標簽和<translate>標簽中有些屬性是相同的,而有些屬性是<scale>標簽特有的,這些屬性的含義如下:
android:fromXScale:表示沿X軸縮放的起始比例。
android:toXScale:表示沿X軸縮放的結束比例。
android:fromYScale:表示沿Y軸縮放的起始比例。
android:toYScale:表示沿Y軸縮放的結束比例。
android:pivotX:表示沿X軸方向縮放的支點位置。如果該屬性值為"50%",則支點在沿X軸中心的位置。
android:pivotY:表示沿Y軸方向縮放的支點位置。如果該屬性值為"50%",則支點在沿Y軸中心的位置。
其中前4個屬性的取值規則如下:
0.0:表示收縮到沒有。
1.0:表示正常不收縮。
大於1.0:表示將組件放大到相應的比例。例如,值為1.5,表示放大到原組件的1.5倍。
小於1.0:表示將組件縮小到相應的比例。例如,值為0.5,表示縮小到原組件的50%。
如果想通過Java代碼實現縮放補間動畫,可以創建android.view.animation.ScaleAnimation對象。ScaleAnimation類構造方法的定義如下:
public ScaleAnimation(float fromX, float toX, float fromY, float toY,float pivotX, float pivotY)
通過ScaleAnimation類的構造方法可以設置上述6個屬性值。設置其他屬性的方法與移動補間動畫相同。
總結
本文主要兩種補間動畫:移動補間動畫和縮放補間動畫,並給出了相應的實例。在下一篇文章中將會介紹另外兩種補間動畫。