天天看點

android glide加載webp動畫設定播放動畫次數和監聽動畫播放完成

需求

産品經理說:需要使用一系列的動畫,我說沒問題啊,用gif圖不就好了嗎?結果,設計師給了我一系列的webp動圖。我能怎麼辦?

先是百度了一番,找到了一個播放webp動畫的glide庫,庫位址是GlideWebpDecoder。

心想,這不就很快搞定了嗎?美滋滋!

一陣操作猛如虎…

引用

def GLIDE_VERSION = "4.9.0"
   // webpdecoder
   implementation "com.zlc.glide:webpdecoder:1.4.${GLIDE_VERSION}"
   // glide 4.6.1~4.9.0 (exclude broken version 4.6.0, 4.7.0)
   implementation "com.github.bumptech.glide:glide:${GLIDE_VERSION}"
   annotationProcessor "com.github.bumptech.glide:compiler:${GLIDE_VERSION}"
           

真正加載webp動态圖

Transformation<Bitmap> circleCrop = new CircleCrop();
				WebpDrawableTransformation webpDrawableTransformation = new WebpDrawableTransformation(circleCrop);
				Glide.with(this).load(R.mipmap.creative).optionalTransform(circleCrop).optionalTransform(WebpDrawable.class, webpDrawableTransformation).into(imageView);
           

簡直是完美解決呀…

稍微等等,我發現

問題

加載倒是能加載出來,但是不能設定加載次數和監聽播放完成。

然後又是百度一番,無果。

最後搜尋glide監聽gif圖檔完成的方法,找到了一個連結,如下

原文出處,根據大佬的方法,通過反射拿到每一張圖檔需要花費的時間,然後發送一個delay事件,就這麼簡單。

代碼

Transformation<Bitmap> circleCrop = new CircleCrop();
   			WebpDrawableTransformation webpDrawableTransformation = new WebpDrawableTransformation(circleCrop);
   			Glide.with(this).load(R.mipmap.creative).addListener(new RequestListener<Drawable>() {

   				@Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
   					return false;
   				}

   				@Override public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {

   					return false;
   				}

   			}).optionalTransform(circleCrop).optionalTransform(WebpDrawable.class, webpDrawableTransformation).into(imageView);
           

先給加載圖檔添加一個監聽webp圖是否準備好了.

然後在監聽的方法中,加上兩個方法,第一個是設定播放次數

private void setLoopCount(WebpDrawable resource,int count) {
   	WebpDrawable webpDrawable = resource;
   	webpDrawable.setLoopCount(count);
   }
           

第二個是通過反射拿到webp動圖播放的時間

private int getWebpPlayTime(Drawable resource) {
   	WebpDrawable webpDrawable = (WebpDrawable) resource;

   	try {
           Field gifStateField = WebpDrawable.class.getDeclaredField("state");
           gifStateField.setAccessible(true);
           Class gifStateClass = Class.forName("com.bumptech.glide.integration.webp.decoder.WebpDrawable$WebpState");
           Field gifFrameLoaderField = gifStateClass.getDeclaredField("frameLoader");
           gifFrameLoaderField.setAccessible(true);

           Class gifFrameLoaderClass = Class.forName("com.bumptech.glide.integration.webp.decoder.WebpFrameLoader");
           Field gifDecoderField = gifFrameLoaderClass.getDeclaredField("gifDecoder");
           gifDecoderField.setAccessible(true);

           Class gifDecoderClass = Class.forName("com.bumptech.glide.gifdecoder.GifDecoder");
           Object gifDecoder = gifDecoderField.get(gifFrameLoaderField.get(gifStateField.get(resource)));
           Method getDelayMethod = gifDecoderClass.getDeclaredMethod("getDelay", int.class);
           getDelayMethod.setAccessible(true);
           // 設定隻播放一次
           // 獲得總幀數
           int count = webpDrawable.getFrameCount();
           int delay = 0;
           for (int i = 0; i < count; i++) {
               // 計算每一幀所需要的時間進行累加
               delay += (int) getDelayMethod.invoke(gifDecoder, i);
           }
           return delay;

       } catch (NoSuchFieldException e) {
           e.printStackTrace();
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       } catch (IllegalAccessException e) {
           e.printStackTrace();
       } catch (NoSuchMethodException e) {
           e.printStackTrace();
       } catch (InvocationTargetException e) {
           e.printStackTrace();
       }
       return 0;
   }
           

然後我們就可以徹底的實作産品經理和設計師的需求了。

等等 ,我好像又發現了一個問題,就是第一次播放完成之後,我會移除目前imageview,但是第二次再播放的時候,發現動畫不動了。尼瑪,

代碼之路處處是坑,通過列印監聽,發現第二次之後都是使用的記憶體緩存。

于是去掉記憶體緩存就好了。

代碼如下:

Transformation<Bitmap> circleCrop = new CircleCrop();
   			WebpDrawableTransformation webpDrawableTransformation = new WebpDrawableTransformation(circleCrop);
   			Glide.with(this).load(R.mipmap.creative).addListener(new RequestListener<Drawable>() {

   				@Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
   					return false;
   				}

   				@Override public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
   					setLoopCount((WebpDrawable) resource,1);
   					int delay = getWebpPlayTime(resource);

   					return false;
   				}

   			}).optionalTransform(circleCrop).optionalTransform(WebpDrawable.class, webpDrawableTransformation).skipMemoryCache(true).into(imageView);
           

徹底解決!