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

来源:互联网 发布:mysql front 乱码 编辑:程序博客网 时间:2024/06/06 01:47
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;@Overrideprotected 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();        }}@Overridepublic 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动画的实现》
7、GradientDrawable:详见《Android开发笔记(十八)书籍翻页动画》


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




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




点此查看Android开发笔记的完整目录
2 0