AndroidでGIFアニメーションを動かすんだもんね

AndroidGIFアニメーション

Androidで画像を表示するときにはImageViewを使います。
しかしImageViewでGIFアニメーションを表示しようとしても
最初の1コマ目が表示されるだけで、2コマ目以降表示されません。
困ったものです。

デコ美のプレビューではどうしているか

ImageViewではアニメーションしてくれないんですが、
WebViewならアニメーションしてくれます。*1
デコ美ではWebViewを一番上に表示しています。
しかしWebViewは重たいです。
おかげでデコ美は落ちまくりです。

ViewでGIFアニメーションを動かす

Movieクラスを使えばViewがCanvasでごにょごにょできるそうです。
難しいことは説明できないです。
javadoc見てください。
Movie | Android Developers
ごめんなさい。javadocに説明なんて一切ないです。なんてこったい。
実装したんでソース見てください。

ソース

public class GIFView extends View {

	private Movie movie;
	private long moviestart;

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

	public GIFView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public GIFView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public void setResouceId(int id) {
		InputStream inputStream = getContext().getResources().openRawResource(id);
		movie = Movie.decodeStream(inputStream);
		moviestart = 0;
	}

	public void setImagePath(String path) {
		try {
			File f = new File(path);
			BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
			bis.mark((int) f.length());
			movie = Movie.decodeStream(bis);
			bis.close();
			moviestart = 0;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	protected void onDraw(Canvas canvas) {
		canvas.drawColor(Color.WHITE);
		if (movie == null) {
			return;
		}
		long now = android.os.SystemClock.uptimeMillis();
		if (moviestart == 0) {
			moviestart = now;
		}
		int relTime = (int) ((now - moviestart) % movie.duration());
		movie.setTime(relTime);
		movie.draw(canvas, 0, 0);
		this.invalidate();
	}
}

かんたん解説

MovieクラスってのがGIFアニメーションを一枚ずつの画像にバラバラにしてくれて、それをCanvasに表示するって感じです。

実は使えません

私のもっているデコメ絵文字を表示したところ3割くらいはちゃんと表示されません。
ぜひお手持ちのGIFアニメーションで試してみてください。
おそらく、ちゃんとGIFのフォーマット通りに作られているGIFファイルであれば表示されるのですが
余計なブロック(コメントブロックやら、謎のブロックやら)があるファイルだとちゃんと表示されないみたいです。
爆発したみたいに表示されます。
次のデコ美もWebViewで行くと思われます。


追記 2010-04-21T22:27:10+09:00
GIFは画像のoffsetを設定できるんですが、それを使っているGIFだとちゃんと表示されないみたいです。
GIFフォーマットの詳細
このサイトがGIFについて詳しい。
Image BlockのImage Left PositionとImage Top Positionが設定されているものだとうまく表示されません。

*1:大きいファイルだと動きませんが