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动画和帧动画代码