博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
53、Gif 控件GifView 的使用,播放gif图片
阅读量:6371 次
发布时间:2019-06-23

本文共 36299 字,大约阅读时间需要 120 分钟。

GifView 是一个为了解决android中现在没有直接显示gif的view,只能通过mediaplay来显示这个问题的项目,其用法和 ImageView一样,支持gif图片。可监视GIF是否加载成功。

GifView的功能: 播放Gif图片 Gif动画监听

Android GifView 的用法:

GifAction.java 观察者类,监视GIF是否加载成功

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

3 public interface GifAction { 4     /** 5      * gif解码观察者 6      * @param parseStatus 解码是否成功,成功会为true 7      * @param frameIndex 当前解码的第几帧,当全部解码成功后,这里为-1 8      */ 9     public void parseOk(boolean parseStatus,int frameIndex);10 }
1 import android.graphics.Bitmap; 2  3 public class GifFrame { 4     /** 5      * 构造函数 6      * @param im 图片 7      * @param del 延时 8      */ 9     public GifFrame(Bitmap im, int del) {10         image = im;11         delay = del;12     }13     /**图片*/14     public Bitmap image;15     /**延时*/16     public int delay;17     /**下一帧*/18     public GifFrame nextFrame = null;19 }
1  import java.io.ByteArrayInputStream;  2 import java.io.InputStream;  3 import android.graphics.Bitmap;  4 import android.graphics.Bitmap.Config;  5   6 public class GifDecoder extends Thread {  7   8     /** 状态:正在解码中 */  9     public static final int STATUS_PARSING = 0; 10     /** 状态:图片格式错误 */ 11     public static final int STATUS_FORMAT_ERROR = 1; 12     /** 状态:打开失败 */ 13     public static final int STATUS_OPEN_ERROR = 2; 14     /** 状态:解码成功 */ 15     public static final int STATUS_FINISH = -1; 16  17     private InputStream in; 18     private int status; 19  20     public int width; // full image width 21     public int height; // full image height 22     private boolean gctFlag; // global color table used 23     private int gctSize; // size of global color table 24     private int loopCount = 1; // iterations; 0 = repeat forever 25  26     private int[] gct; // global color table 27     private int[] lct; // local color table 28     private int[] act; // active color table 29  30     private int bgIndex; // background color index 31     private int bgColor; // background color 32     private int lastBgColor; // previous bg color 33     private int pixelAspect; // pixel aspect ratio 34  35     private boolean lctFlag; // local color table flag 36     private boolean interlace; // interlace flag 37     private int lctSize; // local color table size 38  39     private int ix, iy, iw, ih; // current image rectangle 40     private int lrx, lry, lrw, lrh; 41     private Bitmap image; // current frame 42     private Bitmap lastImage; // previous frame 43     private GifFrame currentFrame = null; 44  45     private boolean isShow = false; 46  47     // current data block 48     private byte[] block = new byte[256]; 49     private int blockSize = 0; // block size 50  51     // last graphic control extension info 52     private int dispose = 0; 53     // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev 54     private int lastDispose = 0; 55     // use transparent color 56     private boolean transparency = false; 57     // delay in milliseconds 58     private int delay = 0; 59     // transparent color index 60     private int transIndex; 61  62     private static final int MaxStackSize = 4096; 63     // max decoder pixel stack size 64  65     // LZW decoder working arrays 66     private short[] prefix; 67     private byte[] suffix; 68     private byte[] pixelStack; 69     private byte[] pixels; 70     // frames read from current file 71     private GifFrame gifFrame; 72     private int frameCount; 73  74     private GifAction action = null; 75  76     private byte[] gifData = null; 77  78     public GifDecoder(byte[] data, GifAction act) { 79         gifData = data; 80         action = act; 81     } 82  83     public GifDecoder(InputStream is, GifAction act) { 84         in = is; 85         action = act; 86     } 87  88     public void run() { 89         if (in != null) { 90             readStream(); 91         } else if (gifData != null) { 92             readByte(); 93         } 94     } 95  96     /** 97      * 释放资源 98      */ 99     public void free() {100         GifFrame fg = gifFrame;101         while (fg != null) {102             fg.image = null;103             fg = null;104             gifFrame = gifFrame.nextFrame;105             fg = gifFrame;106         }107         if (in != null) {108             try {109                 in.close();110             } catch (Exception ex) {111             }112             in = null;113         }114         gifData = null;115     }116 117     /**118      * 当前状态119      * @return120      */121     public int getStatus() {122         return status;123     }124 125     /**126      * 解码是否成功,成功返回true127      * @return 成功返回true,否则返回false128      */129     public boolean parseOk() {130         return status == STATUS_FINISH;131     }132 133     /**134      * 取某帧的延时时间135      * @param n136      *            第几帧137      * @return 延时时间,毫秒138      */139     public int getDelay(int n) {140         delay = -1;141         if ((n >= 0) && (n < frameCount)) {142             // delay = ((GifFrame) frames.elementAt(n)).delay;143             GifFrame f = getFrame(n);144             if (f != null)145                 delay = f.delay;146         }147         return delay;148     }149 150     /**151      * 取所有帧的延时时间152      * @return153      */154     public int[] getDelays() {155         GifFrame f = gifFrame;156         int[] d = new int[frameCount];157         int i = 0;158         while (f != null && i < frameCount) {159             d[i] = f.delay;160             f = f.nextFrame;161             i++;162         }163         return d;164     }165 166     /**167      * 取总帧 数168      * @return 图片的总帧数169      */170     public int getFrameCount() {171         return frameCount;172     }173 174     /**175      * 取第一帧图片176      * @return177      */178     public Bitmap getImage() {179         return getFrameImage(0);180     }181 182     public int getLoopCount() {183         return loopCount;184     }185 186     private void setPixels() {187         int[] dest = new int[width * height];188         // fill in starting image contents based on last image's dispose code189         if (lastDispose > 0) {190             if (lastDispose == 3) {191                 // use image before last192                 int n = frameCount - 2;193                 if (n > 0) {194                     lastImage = getFrameImage(n - 1);195                 } else {196                     lastImage = null;197                 }198             }199             if (lastImage != null) {200                 lastImage.getPixels(dest, 0, width, 0, 0, width, height);201                 // copy pixels202                 if (lastDispose == 2) {203                     // fill last image rect area with background color204                     int c = 0;205                     if (!transparency) {206                         c = lastBgColor;207                     }208                     for (int i = 0; i < lrh; i++) {209                         int n1 = (lry + i) * width + lrx;210                         int n2 = n1 + lrw;211                         for (int k = n1; k < n2; k++) {212                             dest[k] = c;213                         }214                     }215                 }216             }217         }218 219         // copy each source line to the appropriate place in the destination220         int pass = 1;221         int inc = 8;222         int iline = 0;223         for (int i = 0; i < ih; i++) {224             int line = i;225             if (interlace) {226                 if (iline >= ih) {227                     pass++;228                     switch (pass) {229                     case 2:230                         iline = 4;231                         break;232                     case 3:233                         iline = 2;234                         inc = 4;235                         break;236                     case 4:237                         iline = 1;238                         inc = 2;239                     }240                 }241                 line = iline;242                 iline += inc;243             }244             line += iy;245             if (line < height) {246                 int k = line * width;247                 int dx = k + ix; // start of line in dest248                 int dlim = dx + iw; // end of dest line249                 if ((k + width) < dlim) {250                     dlim = k + width; // past dest edge251                 }252                 int sx = i * iw; // start of line in source253                 while (dx < dlim) {254                     // map color and insert in destination255                     int index = ((int) pixels[sx++]) & 0xff;256                     int c = act[index];257                     if (c != 0) {258                         dest[dx] = c;259                     }260                     dx++;261                 }262             }263         }264         image = Bitmap.createBitmap(dest, width, height, Config.ARGB_4444);265     }266 267     /**268      * 取第几帧的图片269      * 270      * @param n271      *            帧数272      * @return 可画的图片,如果没有此帧或者出错,返回null273      */274     public Bitmap getFrameImage(int n) {275         GifFrame frame = getFrame(n);276         if (frame == null)277             return null;278         else279             return frame.image;280     }281 282     /**283      * 取当前帧图片284      * 285      * @return 当前帧可画的图片286      */287     public GifFrame getCurrentFrame() {288         return currentFrame;289     }290 291     /**292      * 取第几帧,每帧包含了可画的图片和延时时间293      * 294      * @param n295      *            帧数296      * @return297      */298     public GifFrame getFrame(int n) {299         GifFrame frame = gifFrame;300         int i = 0;301         while (frame != null) {302             if (i == n) {303                 return frame;304             } else {305                 frame = frame.nextFrame;306             }307             i++;308         }309         return null;310     }311 312     /**313      * 重置,进行本操作后,会直接到第一帧314      */315     public void reset() {316         currentFrame = gifFrame;317     }318 319     /**320      * 下一帧,进行本操作后,通过getCurrentFrame得到的是下一帧321      * 322      * @return 返回下一帧323      */324     public GifFrame next() {325         if (isShow == false) {326             isShow = true;327             return gifFrame;328         } else {329             if (status == STATUS_PARSING) {330                 if (currentFrame.nextFrame != null)331                     currentFrame = currentFrame.nextFrame;332                 // currentFrame = gifFrame;333             } else {334                 currentFrame = currentFrame.nextFrame;335                 if (currentFrame == null) {336                     currentFrame = gifFrame;337                 }338             }339             return currentFrame;340         }341     }342 343     private int readByte() {344         in = new ByteArrayInputStream(gifData);345         gifData = null;346         return readStream();347     }348 349     // public int read(byte[] data){350     // InputStream is = new ByteArrayInputStream(data);351     // return read(is);352     // }353 354     private int readStream() {355         init();356         if (in != null) {357             readHeader();358             if (!err()) {359                 readContents();360                 if (frameCount < 0) {361                     status = STATUS_FORMAT_ERROR;362                     action.parseOk(false, -1);363                 } else {364                     status = STATUS_FINISH;365                     action.parseOk(true, -1);366                 }367             }368             try {369                 in.close();370             } catch (Exception e) {371                 e.printStackTrace();372             }373 374         } else {375             status = STATUS_OPEN_ERROR;376             action.parseOk(false, -1);377         }378         return status;379     }380 381     private void decodeImageData() {382         int NullCode = -1;383         int npix = iw * ih;384         int available, clear, code_mask, code_size, end_of_information,                   in_code, old_code, bits, code, count, i, datum, data_size, first, top, bi, pi;385 386         if ((pixels == null) || (pixels.length < npix)) {387             pixels = new byte[npix]; // allocate new pixel array388         }389         if (prefix == null) {390             prefix = new short[MaxStackSize];391         }392         if (suffix == null) {393             suffix = new byte[MaxStackSize];394         }395         if (pixelStack == null) {396             pixelStack = new byte[MaxStackSize + 1];397         }398         // Initialize GIF data stream decoder.399         data_size = read();400         clear = 1 << data_size;401         end_of_information = clear + 1;402         available = clear + 2;403         old_code = NullCode;404         code_size = data_size + 1;405         code_mask = (1 << code_size) - 1;406         for (code = 0; code < clear; code++) {407             prefix[code] = 0;408             suffix[code] = (byte) code;409         }410 411         // Decode GIF pixel stream.412         datum = bits = count = first = top = pi = bi = 0;413         for (i = 0; i < npix;) {414             if (top == 0) {415                 if (bits < code_size) {416                     // Load bytes until there are enough bits for a code.417                     if (count == 0) {418                         // Read a new data block.419                         count = readBlock();420                         if (count <= 0) {421                             break;422                         }423                         bi = 0;424                     }425                     datum += (((int) block[bi]) & 0xff) << bits;426                     bits += 8;427                     bi++;428                     count--;429                     continue;430                 }431                 // Get the next code.432                 code = datum & code_mask;433                 datum >>= code_size;434                 bits -= code_size;435 436                 // Interpret the code437                 if ((code > available) || (code == end_of_information)) {438                     break;439                 }440                 if (code == clear) {441                     // Reset decoder.442                     code_size = data_size + 1;443                     code_mask = (1 << code_size) - 1;444                     available = clear + 2;445                     old_code = NullCode;446                     continue;447                 }448                 if (old_code == NullCode) {449                     pixelStack[top++] = suffix[code];450                     old_code = code;451                     first = code;452                     continue;453                 }454                 in_code = code;455                 if (code == available) {456                     pixelStack[top++] = (byte) first;457                     code = old_code;458                 }459                 while (code > clear) {460                     pixelStack[top++] = suffix[code];461                     code = prefix[code];462                 }463                 first = ((int) suffix[code]) & 0xff;464                 // Add a new string to the string table,465                 if (available >= MaxStackSize) {466                     break;467                 }468                 pixelStack[top++] = (byte) first;469                 prefix[available] = (short) old_code;470                 suffix[available] = (byte) first;471                 available++;472                 if (((available & code_mask) == 0)473                         && (available < MaxStackSize)) {474                     code_size++;475                     code_mask += available;476                 }477                 old_code = in_code;478             }479 480             // Pop a pixel off the pixel stack.481             top--;482             pixels[pi++] = pixelStack[top];483             i++;484         }485         for (i = pi; i < npix; i++) {486             pixels[i] = 0; // clear missing pixels487         }488     }489 490     private boolean err() {491         return status != STATUS_PARSING;492     }493 494     private void init() {495         status = STATUS_PARSING;496         frameCount = 0;497         gifFrame = null;498         gct = null;499         lct = null;500     }501 502     private int read() {503         int curByte = 0;504         try {505 506             curByte = in.read();507         } catch (Exception e) {508             status = STATUS_FORMAT_ERROR;509         }510         return curByte;511     }512 513     private int readBlock() {514         blockSize = read();515         int n = 0;516         if (blockSize > 0) {517             try {518                 int count = 0;519                 while (n < blockSize) {520                     count = in.read(block, n, blockSize - n);521                     if (count == -1) {522                         break;523                     }524                     n += count;525                 }526             } catch (Exception e) {527                 e.printStackTrace();528             }529             if (n < blockSize) {530                 status = STATUS_FORMAT_ERROR;531             }532         }533         return n;534     }535 536     private int[] readColorTable(int ncolors) {537         int nbytes = 3 * ncolors;538         int[] tab = null;539         byte[] c = new byte[nbytes];540         int n = 0;541         try {542             n = in.read(c);543         } catch (Exception e) {544             e.printStackTrace();545         }546         if (n < nbytes) {547             status = STATUS_FORMAT_ERROR;548         } else {549             tab = new int[256]; // max size to avoid bounds checks550             int i = 0;551             int j = 0;552             while (i < ncolors) {553                 int r = ((int) c[j++]) & 0xff;554                 int g = ((int) c[j++]) & 0xff;555                 int b = ((int) c[j++]) & 0xff;556                 tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b;557             }558         }559         return tab;560     }561 562     private void readContents() {563         // read GIF file content blocks564         boolean done = false;565         while (!(done || err())) {566             int code = read();567             switch (code) {568             case 0x2C: // image separator569                 readImage();570                 break;571             case 0x21: // extension572                 code = read();573                 switch (code) {574                 case 0xf9: // graphics control extension575                     readGraphicControlExt();576                     break;577                 case 0xff: // application extension578                     readBlock();579                     String app = "";580                     for (int i = 0; i < 11; i++) {581                         app += (char) block[i];582                     }583                     if (app.equals("NETSCAPE2.0")) {584                         readNetscapeExt();585                     } else {586                         skip(); // don't care587                     }588                     break;589                 default: // uninteresting extension590                     skip();591                 }592                 break;593             case 0x3b: // terminator594                 done = true;595                 break;596             case 0x00: // bad byte, but keep going and see what happens597                 break;598             default:599                 status = STATUS_FORMAT_ERROR;600             }601         }602     }603 604     private void readGraphicControlExt() {605         read(); // block size606         int packed = read(); // packed fields607         dispose = (packed & 0x1c) >> 2; // disposal method608         if (dispose == 0) {609             dispose = 1; // elect to keep old image if discretionary610         }611         transparency = (packed & 1) != 0;612         delay = readShort() * 10; // delay in milliseconds613         transIndex = read(); // transparent color index614         read(); // block terminator615     }616 617     private void readHeader() {618         String id = "";619         for (int i = 0; i < 6; i++) {620             id += (char) read();621         }622         if (!id.startsWith("GIF")) {623             status = STATUS_FORMAT_ERROR;624             return;625         }626         readLSD();627         if (gctFlag && !err()) {628             gct = readColorTable(gctSize);629             bgColor = gct[bgIndex];630         }631     }632 633     private void readImage() {634         ix = readShort(); // (sub)image position & size635         iy = readShort();636         iw = readShort();637         ih = readShort();638         int packed = read();639         lctFlag = (packed & 0x80) != 0; // 1 - local color table flag640         interlace = (packed & 0x40) != 0; // 2 - interlace flag641         // 3 - sort flag642         // 4-5 - reserved643         lctSize = 2 << (packed & 7); // 6-8 - local color table size644         if (lctFlag) {645             lct = readColorTable(lctSize); // read table646             act = lct; // make local table active647         } else {648             act = gct; // make global table active649             if (bgIndex == transIndex) {650                 bgColor = 0;651             }652         }653         int save = 0;654         if (transparency) {655             save = act[transIndex];656             act[transIndex] = 0; // set transparent color if specified657         }658         if (act == null) {659             status = STATUS_FORMAT_ERROR; // no color table defined660         }661         if (err()) {662             return;663         }664         decodeImageData(); // decode pixel data665         skip();666         if (err()) {667             return;668         }669         frameCount++;670         // create new image to receive frame data671         image = Bitmap.createBitmap(width, height, Config.ARGB_4444);672         // createImage(width, height);673         setPixels(); // transfer pixel data to image674         if (gifFrame == null) {675             gifFrame = new GifFrame(image, delay);676             currentFrame = gifFrame;677         } else {678             GifFrame f = gifFrame;679             while (f.nextFrame != null) {680                 f = f.nextFrame;681             }682             f.nextFrame = new GifFrame(image, delay);683         }684         // frames.addElement(new GifFrame(image, delay)); // add image to frame685         // list686         if (transparency) {687             act[transIndex] = save;688         }689         resetFrame();690         action.parseOk(true, frameCount);691     }692 693     private void readLSD() {694         // logical screen size695         width = readShort();696         height = readShort();697         // packed fields698         int packed = read();699         gctFlag = (packed & 0x80) != 0; // 1 : global color table flag700         // 2-4 : color resolution701         // 5 : gct sort flag702         gctSize = 2 << (packed & 7); // 6-8 : gct size703         bgIndex = read(); // background color index704         pixelAspect = read(); // pixel aspect ratio705     }706 707     private void readNetscapeExt() {708         do {709             readBlock();710             if (block[0] == 1) {711                 // loop count sub-block712                 int b1 = ((int) block[1]) & 0xff;713                 int b2 = ((int) block[2]) & 0xff;714                 loopCount = (b2 << 8) | b1;715             }716         } while ((blockSize > 0) && !err());717     }718 719     private int readShort() {720         // read 16-bit value, LSB first721         return read() | (read() << 8);722     }723 724     private void resetFrame() {725         lastDispose = dispose;726         lrx = ix;727         lry = iy;728         lrw = iw;729         lrh = ih;730         lastImage = image;731         lastBgColor = bgColor;732         dispose = 0;733         transparency = false;734         delay = 0;735         lct = null;736     }737 738     /**739      * Skips variable length blocks up to and including next zero length block.740      */741     private void skip() {742         do {743             readBlock();744         } while ((blockSize > 0) && !err());745     }746 }
1 import java.io.InputStream;  2 import android.content.Context;  3 import android.content.res.Resources;  4 import android.graphics.Bitmap;  5 import android.graphics.Canvas;  6 import android.graphics.Rect;  7 import android.os.Handler;  8 import android.os.Message;  9 import android.os.SystemClock; 10 import android.util.AttributeSet; 11 import android.util.Log; 12 import android.view.View; 13  14 /** 15  * GifView
16 * 本类可以显示一个gif动画,其使用方法和android的其它view(如imageview)一样。
17 * 如果要显示的gif太大,会出现OOM的问题。 18 */ 19 public class GifView extends View implements GifAction { 20 21 /** gif解码器 */ 22 private GifDecoder gifDecoder = null; 23 /** 当前要画的帧的图 */ 24 private Bitmap currentImage = null; 25 26 private boolean isRun = true; 27 28 private boolean pause = false; 29 30 private int showWidth = -1; 31 private int showHeight = -1; 32 private Rect rect = null; 33 34 private DrawThread drawThread = null; 35 36 private GifImageType animationType = GifImageType.SYNC_DECODER; 37 38 /** 39 * 解码过程中,Gif动画显示的方式
40 * 如果图片较大,那么解码过程会比较长,这个解码过程中,gif如何显示 41 * 42 * @author liao 43 * 44 */ 45 public enum GifImageType { 46 /** 47 * 在解码过程中,不显示图片,直到解码全部成功后,再显示 48 */ 49 WAIT_FINISH(0), 50 /** 51 * 和解码过程同步,解码进行到哪里,图片显示到哪里 52 */ 53 SYNC_DECODER(1), 54 /** 55 * 在解码过程中,只显示第一帧图片 56 */ 57 COVER(2); 58 59 GifImageType(int i) { 60 nativeInt = i; 61 } 62 63 final int nativeInt; 64 } 65 66 public GifView(Context context) { 67 super(context); 68 69 } 70 71 public GifView(Context context, AttributeSet attrs) { 72 this(context, attrs, 0); 73 } 74 75 public GifView(Context context, AttributeSet attrs, int defStyle) { 76 super(context, attrs, defStyle); 77 78 } 79 80 /** 81 * 设置图片,并开始解码 82 * 83 * @param gif 84 * 要设置的图片 85 */ 86 private void setGifDecoderImage(byte[] gif) { 87 if (gifDecoder != null) { 88 gifDecoder.free(); 89 gifDecoder = null; 90 } 91 gifDecoder = new GifDecoder(gif, this); 92 gifDecoder.start(); 93 } 94 95 /** 96 * 设置图片,开始解码 97 * 98 * @param is 99 * 要设置的图片100 */101 private void setGifDecoderImage(InputStream is) {102 if (gifDecoder != null) {103 gifDecoder.free();104 gifDecoder = null;105 }106 gifDecoder = new GifDecoder(is, this);107 gifDecoder.start();108 }109 110 /**111 * 以字节数据形式设置gif图片112 * 113 * @param gif114 * 图片115 */116 public void setGifImage(byte[] gif) {117 setGifDecoderImage(gif);118 }119 120 /**121 * 以字节流形式设置gif图片122 * 123 * @param is124 * 图片125 */126 public void setGifImage(InputStream is) {127 setGifDecoderImage(is);128 }129 130 /**131 * 以资源形式设置gif图片132 * 133 * @param resId134 * gif图片的资源ID135 */136 public void setGifImage(int resId) {137 Resources r = this.getResources();138 InputStream is = r.openRawResource(resId);139 setGifDecoderImage(is);140 }141 142 protected void onDraw(Canvas canvas) {143 super.onDraw(canvas);144 if (gifDecoder == null)145 return;146 if (currentImage == null) {147 currentImage = gifDecoder.getImage();148 }149 if (currentImage == null) {150 return;151 }152 int saveCount = canvas.getSaveCount();153 canvas.save();154 canvas.translate(getPaddingLeft(), getPaddingTop());155 if (showWidth == -1) {156 canvas.drawBitmap(currentImage, 0, 0, null);157 } else {158 canvas.drawBitmap(currentImage, null, rect, null);159 }160 canvas.restoreToCount(saveCount);161 }162 163 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {164 int pleft = getPaddingLeft();165 int pright = getPaddingRight();166 int ptop = getPaddingTop();167 int pbottom = getPaddingBottom();168 169 int widthSize;170 int heightSize;171 172 int w;173 int h;174 175 if (gifDecoder == null) {176 w = 1;177 h = 1;178 } else {179 w = gifDecoder.width;180 h = gifDecoder.height;181 }182 183 w += pleft + pright;184 h += ptop + pbottom;185 186 w = Math.max(w, getSuggestedMinimumWidth());187 h = Math.max(h, getSuggestedMinimumHeight());188 189 widthSize = resolveSize(w, widthMeasureSpec);190 heightSize = resolveSize(h, heightMeasureSpec);191 192 setMeasuredDimension(widthSize, heightSize);193 }194 195 /**196 * 只显示第一帧图片
197 * 调用本方法后,gif不会显示动画,只会显示gif的第一帧图198 */199 public void showCover() {200 if (gifDecoder == null)201 return;202 pause = true;203 currentImage = gifDecoder.getImage();204 invalidate();205 }206 207 /**208 * 继续显示动画
209 * 本方法在调用showCover后,会让动画继续显示,如果没有调用showCover方法,则没有任何效果210 */211 public void showAnimation() {212 if (pause) {213 pause = false;214 }215 }216 217 /**218 * 设置gif在解码过程中的显示方式
219 * 本方法只能在setGifImage方法之前设置,否则设置无效220 * 221 * @param type222 * 显示方式223 */224 public void setGifImageType(GifImageType type) {225 if (gifDecoder == null)226 animationType = type;227 }228 229 /**230 * 设置要显示的图片的大小
231 * 当设置了图片大小 之后,会按照设置的大小来显示gif(按设置后的大小来进行拉伸或压缩)232 * 233 * @param width234 * 要显示的图片宽235 * @param height236 * 要显示的图片高237 */238 public void setShowDimension(int width, int height) {239 if (width > 0 && height > 0) {240 showWidth = width;241 showHeight = height;242 rect = new Rect();243 rect.left = 0;244 rect.top = 0;245 rect.right = width;246 rect.bottom = height;247 }248 }249 250 public void parseOk(boolean parseStatus, int frameIndex) {251 if (parseStatus) {252 if (gifDecoder != null) {253 switch (animationType) {254 case WAIT_FINISH:255 if (frameIndex == -1) {256 if (gifDecoder.getFrameCount() > 1) { // 当帧数大于1时,启动动画线程257 DrawThread dt = new DrawThread();258 dt.start();259 } else {260 reDraw();261 }262 }263 break;264 case COVER:265 if (frameIndex == 1) {266 currentImage = gifDecoder.getImage();267 reDraw();268 } else if (frameIndex == -1) {269 if (gifDecoder.getFrameCount() > 1) {270 if (drawThread == null) {271 drawThread = new DrawThread();272 drawThread.start();273 }274 } else {275 reDraw();276 }277 }278 break;279 case SYNC_DECODER:280 if (frameIndex == 1) {281 currentImage = gifDecoder.getImage();282 reDraw();283 } else if (frameIndex == -1) {284 reDraw();285 } else {286 if (drawThread == null) {287 drawThread = new DrawThread();288 drawThread.start();289 }290 }291 break;292 }293 294 } else {295 Log.e("gif", "parse error");296 }297 298 }299 }300 301 private void reDraw() {302 if (redrawHandler != null) {303 Message msg = redrawHandler.obtainMessage();304 redrawHandler.sendMessage(msg);305 }306 }307 308 private Handler redrawHandler = new Handler() {309 public void handleMessage(Message msg) {310 invalidate();311 }312 };313 314 /**315 * 动画线程317 * @author liao319 */320 private class DrawThread extends Thread {321 public void run() {322 if (gifDecoder == null) {323 return;324 }325 while (isRun) {326 if (pause == false) {327 // if(gifDecoder.parseOk()){
328 GifFrame frame = gifDecoder.next();329 currentImage = frame.image;330 long sp = frame.delay;331 if (redrawHandler != null) {332 Message msg = redrawHandler.obtainMessage();333 redrawHandler.sendMessage(msg);334 SystemClock.sleep(sp);335 } else {336 break;337 }338 // }else{339 // currentImage = gifDecoder.getImage();340 // break;341 // }342 } else {343 SystemClock.sleep(10);344 }345 }346 }347 }348 349 }

   以上是Gif用到的所有类库。

   以下是该控件的使用方法。

1 
2
7 8
14 15
22 23
30 31
1 import android.app.Activity; 2 import android.os.Bundle; 3 import android.view.View; 4 import android.view.View.OnClickListener; 6 import com.test.gifview.GifView; 7 import com.test.gifview.GifView.GifImageType; 8  9 public class TestAction extends Activity implements OnClickListener {10 11     private GifView gf1;12     private GifView gf2;13     private boolean f = true;14 15     public void onCreate(Bundle icicle) {16         super.onCreate(icicle);17         // Log.d("dddddddddd",Environment.getRootDirectory().getAbsolutePath());18         // LinearLayout ll = new LinearLayout(this);19         // LayoutParams la = new LayoutParams(LayoutParams.FILL_PARENT,20         // LayoutParams.FILL_PARENT);21         //22         // ll.setLayoutParams(la);23         // gf1 = new GifView(this);24         // gf2 = new GifView(this);25         //26         // gf1.setGifImage(R.drawable.gif1);27         // gf2.setGifImage(R.drawable.gif2);28         //29         // ll.addView(gf1);30         // ll.addView(gf2);31         //32         // setContentView(ll);33 34         setContentView(R.layout.gif);35         gf1 = (GifView) findViewById(R.id.gif1);36         // 设置Gif图片源37         gf1.setGifImage(R.drawable.big_mm);38         // 添加监听器39         gf1.setOnClickListener(this);40 41         gf2 = (GifView) findViewById(R.id.gif2);42         // 设置加载方式:先加载后显示、边加载边显示、只显示第一帧再显示43         gf2.setGifImageType(GifImageType.COVER);44         // 设置显示的大小,拉伸或者压缩45         gf2.setShowDimension(300, 300);46         // 设置Gif图片源47         gf2.setGifImage(R.drawable.a);48         // 添加监听器49         // gf2.setOnClickListener(this);50     }51 52     public void onClick(View v) {53         if (f) {54             // 点击停止动画55             gf1.showCover();56             f = false;57         } else {58             // 点击播放动画59             gf1.showAnimation();60             f = true;61         }62     }63 }

 

转载地址:http://pvuqa.baihongyu.com/

你可能感兴趣的文章
关于VMware Workstation主机列表问题求教
查看>>
配置管理小报101021:给ubuntu加监控
查看>>
qml文字滚动效果的封装,实现方式运用的qml中提供的动画效果,另一种实现方式也可以使用定时器修改控件的坐标来实现...
查看>>
标准C++实现任务队列
查看>>
jdbc url
查看>>
刷leetcode第704题-二分查找
查看>>
debug_backtrace() 函数生成一个 backtrace(追踪)
查看>>
第七天,还是盒子
查看>>
XAMPP软件包下载
查看>>
XXL-JOB初体验-ORACLE版
查看>>
沉思录:别人的棺材
查看>>
jersey + spring + mybatis + redis项目搭建
查看>>
PAT 1006 部分正确_另一种解法
查看>>
在Keil环境下使用JLink实现printf输出重定向至debug窗口
查看>>
postgres的\d命令不显示全部的用户表
查看>>
poj 3468 A Simple Problem with Integers
查看>>
OOA/OOD/OOP细讲
查看>>
Tomcat 系统架构与设计模式_ 设计模式分析
查看>>
Quartz的使用
查看>>
Spring Boot Quartz集成(一)
查看>>