package net.dev123.yibo.widget; import java.io.InputStream; import net.dev123.yibo.common.Constants; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.util.Log; /** * GifView<br> * 本类可以显示一个gif动画,其使用方法和android的其它view(如imageview)一样。<br> * 如果要显示的gif太大,会出现OOM的问题。 */ public class GifView implements GifAction { /**gif解码器*/ private GifDecoder gifDecoder = null; /**当前要画的帧的图*/ private Bitmap currentImage = null; private boolean isRun = true; private boolean pause = false; private DrawThread drawThread = null; private GifImageType animationType = GifImageType.SYNC_DECODER; /** * 解码过程中,Gif动画显示的方式<br> * 如果图片较大,那么解码过程会比较长,这个解码过程中,gif如何显示 * @author liao * */ public enum GifImageType { /** * 在解码过程中,不显示图片,直到解码全部成功后,再显示 */ WAIT_FINISH (0), /** * 和解码过程同步,解码进行到哪里,图片显示到哪里 */ SYNC_DECODER (1), /** * 在解码过程中,只显示第一帧图片 */ COVER (2); GifImageType(int i) { nativeInt = i; } final int nativeInt; } private Context context; private ImageViewTouchBase displayView; public GifView(Context context, ImageViewTouchBase displayView) { this.context = context; this.displayView = displayView; } /** * 设置图片,并开始解码 * @param gif 要设置的图片 */ public void setGifImage(byte[] gifDatabyte) { if (gifDecoder != null) { gifDecoder.free(); gifDecoder = null; } gifDecoder = new GifDecoder(gifDatabyte, this); gifDecoder.start(); } /** * 设置图片,开始解码 * @param is 要设置的图片 */ public void setGifImage(InputStream is) { if (gifDecoder != null) { gifDecoder.free(); gifDecoder = null; } gifDecoder = new GifDecoder(is, this); gifDecoder.start(); } /** * 以资源形式设置gif图片 * @param resId gif图片的资源ID */ public void setGifImage(int resId) { Resources r = context.getResources(); InputStream is = r.openRawResource(resId); setGifImage(is); } /** * 只显示第一帧图片<br> * 调用本方法后,gif不会显示动画,只会显示gif的第一帧图 */ public void showCover() { if (gifDecoder == null) { return; } pause = true; currentImage = gifDecoder.getImage(); reDraw(); } /** * 继续显示动画<br> * 本方法在调用showCover后,会让动画继续显示,如果没有调用showCover方法,则没有任何效果 */ public void showAnimation() { if (pause) { pause = false; } } /** * 设置gif在解码过程中的显示方式<br> * <strong>本方法只能在setGifImage方法之前设置,否则设置无效</strong> * @param type 显示方式 */ public void setGifImageType(GifImageType type) { if (gifDecoder == null) { animationType = type; } } public void parseOk(boolean parseStatus, int frameIndex) { isRun = true; if (!parseStatus || gifDecoder == null) { if (Constants.DEBUG) Log.e("gif","parse error"); return; } switch(animationType) { case WAIT_FINISH: if (frameIndex == -1) { if (gifDecoder.getFrameCount() >= 1) { //当帧数大于1时,启动动画线程 DrawThread dt = new DrawThread(); dt.start(); } else { reDraw(); } } break; case COVER: if (frameIndex == 1) { GifFrame frame = gifDecoder.next(); currentImage = frame.image; reDraw(); } else if(frameIndex == -1) { if (gifDecoder.getFrameCount() >= 1) { if (drawThread == null) { drawThread = new DrawThread(); drawThread.start(); } } else { reDraw(); } } break; case SYNC_DECODER: if (frameIndex == 1) { GifFrame frame = gifDecoder.next(); currentImage =frame.image; reDraw(); } else if(frameIndex == -1) { reDraw(); } else { if (drawThread == null) { drawThread = new DrawThread(); drawThread.start(); } } break; } } private void reDraw() { if (redrawHandler != null) { Message msg = redrawHandler.obtainMessage(); redrawHandler.sendMessage(msg); } } private Handler redrawHandler = new Handler(){ @Override public void handleMessage(Message msg) { if (displayView == null || currentImage == null || currentImage.isRecycled() == true) { return; } displayView.setImageBitmap(currentImage); } }; public void destroy() { isRun = false; if (gifDecoder != null) { gifDecoder.free(); gifDecoder = null; } drawThread = null; if (currentImage != null && !currentImage.isRecycled()) { currentImage.recycle(); } currentImage = null; pause = false; } /** * 动画线程 */ private class DrawThread extends Thread { public void run() { if (gifDecoder == null) { return; } while (isRun) { if (pause == false) { if (gifDecoder == null) { SystemClock.sleep(10); continue; } GifFrame frame = gifDecoder.next(); if (frame == null) { SystemClock.sleep(10); continue; } currentImage = frame.image; long sp = frame.delay; if (redrawHandler != null) { Message msg = redrawHandler.obtainMessage(); redrawHandler.sendMessage(msg); int status = (gifDecoder != null ? gifDecoder.getStatus() : GifDecoder.STATUS_PARSING); if (status == GifDecoder.STATUS_PARSING) { //sp = sp/4; } SystemClock.sleep(sp); } else { break; } } else { SystemClock.sleep(10); } } } } }