如何在Android中顯示GIF動畫,有很多方法,比如可以使用J2ME平臺上那個解碼工具類,純java的,拿來即可。
但是其實Android還是爲我們提供了一個更爲方便的工具:android.graphics.Movie。
參考例子在ApiDemos中的BitmapDecode中。
下面我只是簡單地用它來實現一個自己的GIFView,以方便在各種需要使用GIF動畫的場合使用。
爲了簡單,我讓GIFView extends ImageView罷了。它在佈局中的描述如下:
- <cn.sharetop.android.view.GIFView
- android:id="@+id/gif"
- android:layout_gravity="center_horizontal"
- android:layout_width="278px"
- android:layout_height="183px"
- android:scaleType="fitXY"
- app:gif="@drawable/a"
- android:src="@drawable/a"
- />
與ImageView唯一的區別在於我加了一個gif屬性,與src屬性的值是一樣的。不過它們需要同時存在,不可省略其中之一(後面我會說明爲什麼)。
注意因爲gif屬性,所以別忘了那個attr.xml中也要加上:
- <resources>
- <declare-styleable name="GIFView">
- <attr name="gif" format="reference" />
- </declare-styleable>
- </resources>
然後是代碼,沒幾行的:
- public class GIFView extends ImageView {
- private static final String TAG="GIFView";
- private Movie mMovie;
- private long mMovieStart;
- //此處省略幾個構造函數
- //......
- //主要的構造函數
- public GIFView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- // TODO Auto-generated constructor stub
- mMovie=null;
- mMovieStart=0;
- //從描述文件中讀出gif的值,創建出Movie實例
- TypedArray a = context.obtainStyledAttributes(attrs,
- R.styleable.GIFView, defStyle, 0);
- int srcID=a.getResourceId(R.styleable.GIFView_gif, 0);
- if(srcID>0){
- InputStream is = context.getResources().openRawResource(srcID);
- mMovie = Movie.decodeStream(is);
- }
- a.recycle();
- }
- //主要的工作是重載onDraw
- @Override
- protected void onDraw(Canvas canvas) {
- // TODO Auto-generated method stub
- //super.onDraw(canvas);
- //當前時間
- long now = android.os.SystemClock.uptimeMillis();
- //如果第一幀,記錄起始時間
- if (mMovieStart == 0) { // first time
- mMovieStart = now;
- }
- if (mMovie != null) {
- //取出動畫的時長
- int dur = mMovie.duration();
- if (dur == 0) {
- dur = 1000;
- }
- //算出需要顯示第幾幀
- int relTime = (int)((now - mMovieStart) % dur);
- //Log.d(TAG,"---onDraw..."+mMovie.toString()+",,,,"+relTime);
- //設置要顯示的幀,繪製即可
- mMovie.setTime(relTime);
- mMovie.draw(canvas,0,0);
- invalidate();
- }
- }
- }
代碼中已有註釋,就不多說了。我的理解是Movie其實管理着GIF動畫中的多個幀,只需要通過 setTime() 一下就可以讓它在draw()的時候繪出相應的那幀圖像。
通過當前時間與duration之間的換算關係,是很容易實現GIF動起來的效果。
最後,說一下爲什麼src與gif要同時存在了,因爲我這個GIFView很簡單,沒有自己去onMeasure,所以要藉助src讓ImageView去計算它的尺寸和佈局之類的事情。
只是在onDraw的時候,不顯示src而已。
如果感興趣的同學可以自己完善這個GIFView,比如以下兩點:
1. 只需要一個gif屬性,不要src了,或者直接使用src屬性?
2. 如果在xml中沒有指定gif/src的值,增加一些方法讓用戶可以通過代碼設置gif和src的值
[補充]
剛纔又覺得這段代碼有修正的必要:
1. 關於如何直接使用src這個屬性,仍是修改attr.xml中,這樣即可:
- <resources>
- <declare-styleable name="GIFView">
- <attr name="android:src" />
- </declare-styleable>
- </resources>
然後在main.xml中就不再需要gif這個屬性,直接用src就可以了。