Android中动态显示gif图片

尹俊雅
2023-12-01

android所带的控件里面没有能够显示gif图片的

网上的解决方法大致有三种

第一:先将gif图片分拆为N帧(由美工/软件完成),然后逐次播放;

第二:利用java代码将图片分拆为N帧;

第三:android里面有一个Movie类,可以使用它来播放gif动画(此类位于android.graphics包下)

前面两种的思路是一样的,第二种网上有jar包可以下载用(在资源中已经上传)。

第一种对于帧数较多的图片太过于繁琐,不提倡使用。

先来解释一下第二种的方法:

GifAction.java 观察者类,监视GIF是否加载成功
GifFrame.java 里面三个成员:当前图片、延时、下张Frame的链接。
GifDecoder.java 解码线程类
GifView.java 主类,包括常用方法,如GifView构造方法、设置图片源、延迟、绘制等。

 

public interface GifAction {

	/**
	 * gif解码观察者
	 * @param parseStatus 解码是否成功,成功会为true
	 * @param frameIndex 当前解码的第几帧,当全部解码成功后,这里为-1
	 */
	public void parseOk(boolean parseStatus,int frameIndex);
}


 

//线程操作gif图片解码
public class GifDecoder extends Thread


 

//gif框架
public class GifFrame
{
	/**
	 * 构造函数
	 * 
	 * @param im
	 *            图片
	 * @param del
	 *            延时
	 */
	public GifFrame(Bitmap im, int del)
	{
		image = im;
		delay = del;
	}

	/** 图片 */
	public Bitmap image;
	/** 延时 */
	public int delay;
	/** 下一帧 */
	public GifFrame nextFrame = null;
}


 

/**
 * GifView<br>
 * 本类可以显示一个gif动画,其使用方法和android的其它view(如imageview)一样。<br>
 * 如果要显示的gif太大,会出现OOM的问题。
 * 
 * @author liao
 * 
 */
public class GifView extends View implements GifAction


 

应用如下:

1-把GifView.jar加入你的项目。
2-在xml中配置GifView的基本属性,GifView继承自View类,和Button、ImageView一样是一个UI控件。如:
<com.ant.liao.GifView android:id="@+id/gif2"
 android:layout_height="wrap_content" android:layout_width="wrap_content"
 android:paddingTop="4px" android:paddingLeft="14px" android:enabled="false" />
3-在代码中配置常用属性:
// 从xml中得到GifView的句柄
gf1 = (GifView) findViewById(R.id.gif1);
// 设置Gif图片源
gf1.setGifImage(R.drawable.gif1);
// 添加监听器
gf1.setOnClickListener(this);
// 设置显示的大小,拉伸或者压缩
gf1.setShowDimension(300, 300);
// 设置加载方式:先加载后显示、边加载边显示、只显示第一帧再显示
gf1.setGifImageType(GifImageType.COVER);

 

然后分析下第三种方法:

,为了显示gif图片,我们需要用到Movie类和自定义控件(包括自定义属性)

首先,我们来自定义控件属性:

在res/values里面建立xml文件,习惯性命名为attrs.xml(可以命名为其他名字)

在attrs.xml里面增加属性如下:

<declare-styleable name="GifView">
        <attr name="src" format="integer" />    

</declare-styleable>

 

这里我只增加了一个属性,就是设置src文件。

属性设置好了,那怎么将这个src属性与java代码对应起来呢,这个就需要到构造函数里面处理了

public GifView(Context context, AttributeSet attrs){
  super(context, attrs);
  TypedArray ta = context.obtainStyledAttributes(attrs,  
                R.styleable.GifView);  //这里用到了attrs.xml里面定义的GifView
  int taCount = ta.length();   //获得属性的个数
  
  for (int i=0;i<taCount;i++){  //处理所有属性,由于我只定义了一个src属性,所以就只处理src属性
   if (R.styleable.GifView_src == ta.getIndex(i)) {
    int id = ta.getResourceId(R.styleable.GifView_src, 0); //这里的参数是前面的GifView + _ + src链接起来
    if (0 != id) {
     setSrc(id);  //对应的函数,即在xml里面设置了src,相应的处理就会在setSrc函数里面进行
    }
   }
  }
  ta.recycle();
 }

 


下面是setSrc函数:

public void setSrc(int id){
  gifMovie = Movie.decodeStream(getResources().openRawResource(id)); //gifMovie为Movie类型
 }


接下来是view的onDraw函数,这也是绘画动画的关键

public void onDraw(Canvas canvas){
   long now = android.os.SystemClock.uptimeMillis(); //获得当前时间
         if (lStartTime == 0) {   // first time
          lStartTime = now;
         }
         if (gifMovie != null) {
             int dur = gifMovie.duration();  //获得gif文件的动画周期
             if (dur == 0) {
                 dur = 1000;
             }
             int relTime = (int)((now - lStartTime) % dur);
             gifMovie.setTime(relTime);  //设置播放时间点
             gifMovie.draw(canvas, getWidth() - gifMovie.width(),  //播放(即绘画)
                         getHeight() - gifMovie.height());
             invalidate();
         }

}


 

下面在main.xml文件里面加入自定义的GifView控件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:gif="http://schemas.android.com/apk/res/com.gif.demo"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    />
<com.gif.demo.GifView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 gif:src="@drawable/lion"
/>
</LinearLayout>


其中xmlns:gif="http://schemas.android.com/apk/res/com.gif.demo"
即gif为自己定义的namespace,com.gif.demo对应于自己的包名,即activity对应的包名

最后在activity里面setContentView(R.layout.main)就ok了

 类似资料: