天天看點

android中播放gif動畫之二

随時随地閱讀更多技術實戰幹貨,擷取項目源碼、學習資料,請關注源代碼社群公衆号(ydmsq666)、QQ技術交流群(183198395)。

android中播放gif動畫之二
android中播放gif動畫之二
android中播放gif動畫之二

在上一篇,是使用代碼通過構造方法傳入要播放的gif動畫的id進行擷取的。本文進一步改造,讓GifView和ImageView一樣可以在布局檔案中設定src屬性,并在GifView中我們使用反射動态擷取src的圖檔資源ID,然後對它進行播放。這樣使用起來就靈活多了。代碼如下:

GifView:

package com.home.gifview;

import java.io.InputStream;
import java.lang.reflect.Field;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.ImageView;

public class GifView extends ImageView {

	private Movie movie;
	private long movieStart;
	private int imageWidth;
	private int imageHeight;

	public GifView(Context context) {
		super(context);
	}

	public GifView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public GifView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		TypedArray a = context.obtainStyledAttributes(attrs,
				R.styleable.GifView);
		int resourceId = getResourceId(a, context, attrs);
		if (resourceId != 0) {
			InputStream is = getResources().openRawResource(resourceId);
			movie = Movie.decodeStream(is);
			if (movie != null) {
				Bitmap bitmap = BitmapFactory.decodeStream(is);
				imageWidth = bitmap.getWidth();
				imageHeight = bitmap.getHeight();
				bitmap.recycle();
			}
		}
	}

	@Override
	protected void onDraw(Canvas canvas) {
		if (movie == null) {
			// 普通圖檔則直接調用父類的onDraw()方法
			super.onDraw(canvas);
		} else {
			playGif(canvas);
			invalidate();
		}
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		if (movie != null) {
			// 如果是gif圖檔則定制GifView的大小
			setMeasuredDimension(imageWidth, imageHeight);
		}
	}

	/**
	 * 播放gif動畫
	 * 
	 * @param canvas
	 * @return
	 */
	private boolean playGif(Canvas canvas) {
		long now = SystemClock.uptimeMillis();
		if (movieStart == 0) {
			movieStart = now;
		}
		int duration = movie.duration();
		if (duration == 0) {
			duration = 1000;
		}
		int relTime = (int) ((now - movieStart) % duration);
		movie.setTime(relTime);
		movie.draw(canvas, 0, 0);
		if ((now - movieStart) >= duration) {
			movieStart = 0;
			return true;
		}
		return false;
	}

	/**
	 * 使用反射,擷取到src指定圖檔資源所對應的id。
	 * 
	 * @param a
	 * @param context
	 * @param attrs
	 * @return
	 */
	private int getResourceId(TypedArray a, Context context, AttributeSet attrs) {
		try {
			Field field = TypedArray.class.getDeclaredField("mValue");
			field.setAccessible(true);
			TypedValue typedValueObject = (TypedValue) field.get(a);
			return typedValueObject.resourceId;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (a != null) {
				a.recycle();
			}
		}
		return 0;
	}
}
           

attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="GifView"></declare-styleable>

</resources>
           

main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.home.gifview.GifView
        android:id="@+id/main_gifView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:src="@drawable/loading" />

</RelativeLayout>
           

禁用硬體加速:

android:hardwareAccelerated="false"