package com.d3.d3xmpp.d3View.gifView; import java.io.InputStream; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.os.Handler; import android.os.Message; import android.os.Parcelable; import android.os.SystemClock; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.widget.ImageView; /** * GifView<br> * ���������ʾһ��gif��������ʹ�÷�����android������view����imageview)һ����<br> * ���Ҫ��ʾ��gif̫�󣬻����OOM�����⡣���嵽tmp * @author liao * */ public class GifView extends ImageView implements GifAction{ /**gif������*/ private GifDecoder gifDecoder = null; /**��ǰҪ����֡��ͼ*/ private Bitmap currentImage = null; private boolean isRun = true; private boolean pause = false; private DrawThread drawThread = null; private Context context = null; private boolean cacheImage = false; private View backView = 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; } public GifView(Context context) { super(context); this.context = context; //gifDecoder = new GifDecoder(this); setScaleType(ImageView.ScaleType.FIT_XY); } public GifView(Context context, AttributeSet attrs) { this(context, attrs,0); } public GifView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.context = context; // TypedArray a = context.obtainStyledAttributes(attrs,R.array.); //gifDecoder = new GifDecoder(this); setScaleType(ImageView.ScaleType.FIT_XY); } /** * ����ͼƬ������ʼ���� * @param gif Ҫ���õ�ͼƬ */ private void setGifDecoderImage(byte[] gif){ if(gifDecoder == null){ gifDecoder = new GifDecoder(this); } gifDecoder.setGifImage(gif); gifDecoder.start(); } /** * ����ͼƬ����ʼ���� * @param is Ҫ���õ�ͼƬ */ private void setGifDecoderImage(InputStream is){ if(gifDecoder == null){ gifDecoder = new GifDecoder(this); } gifDecoder.setGifImage(is); gifDecoder.start(); } /** * �ѱ�Gif��������Ϊ����view�ı��� * @param v Ҫʹ��gif��Ϊ������view */ public void setAsBackground(View v){ backView = v; } protected Parcelable onSaveInstanceState() { super.onSaveInstanceState(); if(gifDecoder != null) gifDecoder.free(); return null; } /** * @hide * ���û���ͼƬ<br> * �������ͼƬ��ÿһFrame�ļ��̫��Ļ����������֡������<br> * ��������˻���ͼƬ������������destroy��������ͼƬ������ */ // public void setCahceImage(){ // if(gifDecoder == null){ // gifDecoder = new GifDecoder(this); // } // cacheImage = true; // gifDecoder.setCacheImage(true, context); // } /** * ���ֽ�������ʽ����gifͼƬ * @param gif ͼƬ */ public void setGifImage(byte[] gif){ setGifDecoderImage(gif); } /** * ���ֽ�����ʽ����gifͼƬ * @param is ͼƬ */ public void setGifImage(InputStream is){ setGifDecoderImage(is); } /** * ����Դ��ʽ����gifͼƬ * @param resId gifͼƬ����ԴID */ public void setGifImage(int resId){ if (currentImage != null) { currentImage = null; } if (gifDecoder != null) { stopDecodeThread(); gifDecoder = null; } Resources r = getResources(); InputStream is = r.openRawResource(resId); setGifDecoderImage(is); } /** * �жϽ����߳� */ private void stopDecodeThread() { if (gifDecoder != null && gifDecoder.getState() != Thread.State.TERMINATED) { gifDecoder.interrupt(); gifDecoder.destroy(); } } public void destroy(){ if(gifDecoder != null) gifDecoder.free(); } /** * ֻ��ʾ��һ֡ͼƬ<br> * ���ñ�������gif������ʾ������ֻ����ʾgif�ĵ�һ֡ͼ */ public void showCover(){ if(gifDecoder == null) return; pause = true; currentImage = gifDecoder.getImage(); invalidate(); } /** * ������ʾ����<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; } /** * @hide */ public void parseOk(boolean parseStatus,int frameIndex){ if(parseStatus){ if(gifDecoder != null){ 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){ currentImage = gifDecoder.getImage(); 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){ currentImage = gifDecoder.getImage(); reDraw(); }else if(frameIndex == -1){ reDraw(); }else{ if(drawThread == null){ drawThread = new DrawThread(); drawThread.start(); } } break; } }else{ Log.e("gif","parse error"); } } } private void reDraw(){ if(redrawHandler != null){ Message msg = redrawHandler.obtainMessage(); redrawHandler.sendMessage(msg); } } private void drawImage(){ setImageBitmap(currentImage); invalidate(); } private Handler redrawHandler = new Handler(){ public void handleMessage(Message msg) { try{ if(backView != null){ backView.setBackgroundDrawable(new BitmapDrawable(currentImage)); }else{ drawImage(); } }catch(Exception ex){ Log.e("GifView", ex.toString()); } } }; /** * �����߳� * @author liao * */ private class DrawThread extends Thread{ public void run(){ if(gifDecoder == null){ return; } while(isRun){ if (pause == false) { GifFrame frame = gifDecoder.next(); if (frame == null) { SystemClock.sleep(50); continue; } if (frame.image != null) currentImage = frame.image; else if (frame.imageName != null) { currentImage = BitmapFactory.decodeFile(frame.imageName); } long sp = frame.delay; if (redrawHandler != null) { reDraw(); SystemClock.sleep(sp); } else { break; } } else { SystemClock.sleep(50); } } } } }