package com.ijoomer.customviews; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.util.AttributeSet; import android.view.View; import android.widget.LinearLayout.LayoutParams; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; public class IjoomerGifView extends View { public static final int IMAGE_TYPE_UNKNOWN = 0; public static final int IMAGE_TYPE_STATIC = 1; public static final int IMAGE_TYPE_DYNAMIC = 2; public static final int DECODE_STATUS_UNDECODE = 0; public static final int DECODE_STATUS_DECODING = 1; public static final int DECODE_STATUS_DECODED = 2; private GifDecoder decoder; private Bitmap bitmap; public int imageType = IMAGE_TYPE_UNKNOWN; public int decodeStatus = DECODE_STATUS_UNDECODE; private int width; private int height; private long time; private int index; private int resId; private String filePath; private boolean playFlag = false; int gifImageResourceID; public IjoomerGifView(Context context, AttributeSet attrs) { super(context, attrs); String namespace = "http://schemas.android.com/apk/res/" + context.getPackageName(); gifImageResourceID = attrs.getAttributeResourceValue(namespace, "gif_image", 0); if (gifImageResourceID != 0) { setGifImageResourceID(gifImageResourceID); } } /** * Constructor */ public IjoomerGifView(Context context) { super(context); } private InputStream getInputStream() { if (filePath != null) try { return new FileInputStream(filePath); } catch (FileNotFoundException e) { } if (resId > 0) return getContext().getResources().openRawResource(resId); return null; } /** * set gif file path * * @param filePath */ public void setGif(String filePath) { Bitmap bitmap = BitmapFactory.decodeFile(filePath); setGif(filePath, bitmap); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (bitmap != null) { setMeasuredDimension(MeasureSpec.getSize(bitmap.getWidth()), MeasureSpec.getSize(bitmap.getHeight())); } } /** * set gif file path and cache image * * @param filePath * @param cacheImage */ public void setGif(String filePath, Bitmap cacheImage) { this.resId = 0; this.filePath = filePath; imageType = IMAGE_TYPE_UNKNOWN; decodeStatus = DECODE_STATUS_UNDECODE; playFlag = false; bitmap = cacheImage; width = bitmap.getWidth(); height = bitmap.getHeight(); android.view.ViewGroup.LayoutParams params = getLayoutParams(); params.width = width; params.height = height; setLayoutParams(params); play(); } /** * set gif resource id * * @param resId */ public void setGifImageResourceID(int resId) { Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId); setGif(resId, bitmap); } /** * set gif resource id and cache image * * @param resId * @param cacheImage */ public void setGif(int resId, Bitmap cacheImage) { this.filePath = null; this.resId = resId; imageType = IMAGE_TYPE_UNKNOWN; decodeStatus = DECODE_STATUS_UNDECODE; playFlag = false; bitmap = cacheImage; width = bitmap.getWidth(); height = bitmap.getHeight(); setLayoutParams(new LayoutParams(width, height)); play(); } private void decode() { release(); index = 0; decodeStatus = DECODE_STATUS_DECODING; new Thread() { @Override public void run() { decoder = new GifDecoder(); decoder.read(getInputStream()); if (decoder.width == 0 || decoder.height == 0) { imageType = IMAGE_TYPE_STATIC; } else { imageType = IMAGE_TYPE_DYNAMIC; } postInvalidate(); time = System.currentTimeMillis(); decodeStatus = DECODE_STATUS_DECODED; } }.start(); } public void release() { decoder = null; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (decodeStatus == DECODE_STATUS_UNDECODE) { canvas.drawBitmap(bitmap, (getWidth()-width)/2, (getHeight()-height)/2, null); if (playFlag) { decode(); invalidate(); } } else if (decodeStatus == DECODE_STATUS_DECODING) { canvas.drawBitmap(bitmap, (getWidth()-width)/2, (getHeight()-height)/2, null); invalidate(); } else if (decodeStatus == DECODE_STATUS_DECODED) { if (imageType == IMAGE_TYPE_STATIC) { canvas.drawBitmap(bitmap, (getWidth()-width)/2, (getHeight()-height)/2, null); } else if (imageType == IMAGE_TYPE_DYNAMIC) { if (playFlag) { long now = System.currentTimeMillis(); if (time + decoder.getDelay(index) < now) { time += decoder.getDelay(index); incrementFrameIndex(); } Bitmap bitmap = decoder.getFrame(index); if (bitmap != null) { canvas.drawBitmap(bitmap, (getWidth()-width)/2, (getHeight()-height)/2, null); } invalidate(); } else { Bitmap bitmap = decoder.getFrame(index); canvas.drawBitmap(bitmap, (getWidth()-width)/2, (getHeight()-height)/2, null); } } else { canvas.drawBitmap(bitmap, (getWidth()-width)/2, (getHeight()-height)/2, null); } } } private void incrementFrameIndex() { index++; if (index >= decoder.getFrameCount()) { index = 0; } } private void decrementFrameIndex() { index--; if (index < 0) { index = decoder.getFrameCount() - 1; } } public void play() { time = System.currentTimeMillis(); playFlag = true; invalidate(); } public void pause() { playFlag = false; invalidate(); } public void stop() { playFlag = false; index = 0; invalidate(); } public void nextFrame() { if (decodeStatus == DECODE_STATUS_DECODED) { incrementFrameIndex(); invalidate(); } } public void prevFrame() { if (decodeStatus == DECODE_STATUS_DECODED) { decrementFrameIndex(); invalidate(); } } }