Android开发笔记(十七)GIF动画的实现GifAnimation

GIF在Windows上是常见的图片格式,主要用来播放短小的动画。但在手机上由于系统资源紧张,所以Android并没有直接支持GIF格式,如果在ImageView中放入一张gif文件,你会发现显示出来的只是该gif文件的第一帧图片。


对于这种情况,Android带来了帧动画技术,通过连续播放每帧图片,从而实现帧动画的效果。不过若要使用帧动画,我们得自己准备好若干帧,然后把这些图片帧编入图片队列,这样才可以显示动画。对于如何从gif文件中提取出每帧图片,博主在之前的文章中有做了说明,详见《 Android开发笔记(十)常用的图片加工操作》。


可是手工分解gif文件也太麻烦了,如果gif数量多的话,岂不累坏了。能否通过代码直接从gif文件中提取每帧图片呢?答案是有的,已经有大牛研究出来了,那么我们直接把相关算法拿过来,改改就可以用了。下面是调用的代码例子,为方便比较帧动画和GIF动画的效果,代码同时实现了两种动画
import java.io.InputStream;

import com.example.exmgif.util.GifImage;
import com.example.exmgif.util.GifImage.GifFrame;

import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {

	private ImageView iv_gif;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		Button btn_play1 = (Button) findViewById(R.id.btn_play1);
		Button btn_play2 = (Button) findViewById(R.id.btn_play2);
		btn_play1.setOnClickListener(this);
		btn_play2.setOnClickListener(this);
		iv_gif = (ImageView) findViewById(R.id.iv_gif);
	}
	
	private Drawable getDraw(int id) {
		return getResources().getDrawable(id);
	}
	
	private void showFrameAnimation() {
		//帧动画需要把每帧图片加入AnimationDrawable队列
		AnimationDrawable animationList = new AnimationDrawable();
		animationList.addFrame(getDraw(R.drawable.flow_p1), 50);
		animationList.addFrame(getDraw(R.drawable.flow_p2), 50);
		animationList.addFrame(getDraw(R.drawable.flow_p3), 50);
		animationList.addFrame(getDraw(R.drawable.flow_p4), 50);
		animationList.addFrame(getDraw(R.drawable.flow_p5), 50);
		animationList.addFrame(getDraw(R.drawable.flow_p6), 50);
		animationList.addFrame(getDraw(R.drawable.flow_p7), 50);
		animationList.addFrame(getDraw(R.drawable.flow_p8), 50);
		//setOneShot为true表示只播放一次,为false表示循环播放
		animationList.setOneShot(false);
		iv_gif.setImageDrawable(animationList);
		animationList.start();
	}

	private void showGifAnimation(int resid) {
		InputStream is = getResources().openRawResource(resid);
		GifImage gifImage = new GifImage();
		int code = gifImage.read(is);
		if (code == GifImage.STATUS_OK) {  
			GifFrame[] frameList = gifImage.getFrames();
			AnimationDrawable gifList = new AnimationDrawable();
			for (int i=0; i<frameList.length; i++) {
				//BitmapDrawable用于把Bitmap格式转换为Drawable格式
				BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), frameList[i].image);
				gifList.addFrame(bitmapDrawable, frameList[i].delay);
			}
			gifList.setOneShot(false);
			iv_gif.setImageDrawable(gifList);
			gifList.start();
        } else if (code == GifImage.STATUS_FORMAT_ERROR) {
			Toast.makeText(this, "该图片不是gif格式", Toast.LENGTH_LONG).show();
        } else {
			Toast.makeText(this, "gif图片读取失败:"+code, Toast.LENGTH_LONG).show();
        }
	}
	
	@Override
	public void onClick(View v) {
		if (v.getId() == R.id.btn_play1) {
			showFrameAnimation();
		} else if (v.getId() == R.id.btn_play2) {
			showGifAnimation(R.drawable.welcome);
		}
	}

}

可以看到帧动画并非补间动画那样有专门的Animation类,而是通过AnimationDrawable来实现(又是Drawable)。另外,代码在从gif文件抽取每帧图片时,用到了BitmapDrawable,该类可把Bitmap格式转换为Drawable格式。不知不觉,我们已经应用了十几个Drawable中的大半,它们分别是:
1、StateListDrawable:详见《 Android开发笔记(七)初识Drawable》
2、ShapeDrawable:详见《 Android开发笔记(八)神奇的shape》
3、NinePatchDrawable:详见《 Android开发笔记(九)特别的.9图片》
4、TransitionDrawable:详见《 Android开发笔记(十五)淡入淡出动画》
5、AnimationDrawable:见本文《Android开发笔记(十七)GIF动画的实现》
6、BitmapDrawable:见本文《Android开发笔记(十七)GIF动画的实现》


下面是GIF动画和帧动画的效果图




点击下载本文用到的GIF动画和帧动画代码





你可能感兴趣的:(android,帧动画,gif动画,GifAnimation)