前言
這篇blog主要記錄一下最近剛好遇見的問題肄鸽,要實(shí)現(xiàn)一個gif只播放一次并且要在gif播放完之后回調(diào)一下的需求女淑,項(xiàng)目目前用的Glide是4.0版本,這個問題如果在Glide3.7上那么很好解決,網(wǎng)上有一大把的代碼示例勇哗,但是在Glide4.0的版本上壕曼,怎么搜都搜不到類似的苏研,只好自己想方法解決了,好了廢話不多說腮郊。
解決方法
一般在Glide3.7的時候是這樣解決的摹蘑,
Glide.with(this)
.load("xxxurl")
.listener(new RequestListener<Integer, GlideDrawable>() {
@Override
public boolean onException(Exception arg0, Integer arg1,
Target<GlideDrawable> arg2, boolean arg3) {
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource,
Integer model, Target<GlideDrawable> target,
boolean isFromMemoryCache, boolean isFirstResource) {
// 計(jì)算動畫時長
GifDrawable drawable = (GifDrawable) resource;
GifDecoder decoder = drawable.getDecoder();
for (int i = 0; i < drawable.getFrameCount(); i++) {
duration += decoder.getDelay(i);
}
//發(fā)送延時消息,通知動畫結(jié)束
handler.sendEmptyMessageDelayed(MESSAGE_SUCCESS,
duration);
return false;
}
}) //僅僅加載一次gif動畫
.into(new GlideDrawableImageViewTarget(imageview, 1));
但是在Glide4.0中伴榔,沒法再直接獲取GifDecoder
對象了纹蝴,原因是因?yàn)?code>GlideDrawable不再提供這個方法了。
我這里是采用反射的方法獲取到GifDecoder變量的踪少,具體代碼如下:
public static void loadOneTimeGif(Context context, Object model, final ImageView imageView, final GifListener gifListener) {
Glide.with(context).asGif().load(model).listener(new RequestListener<GifDrawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<GifDrawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(GifDrawable resource, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {
try {
Field gifStateField = GifDrawable.class.getDeclaredField("state");
gifStateField.setAccessible(true);
Class gifStateClass = Class.forName("com.bumptech.glide.load.resource.gif.GifDrawable$GifState");
Field gifFrameLoaderField = gifStateClass.getDeclaredField("frameLoader");
gifFrameLoaderField.setAccessible(true);
Class gifFrameLoaderClass = Class.forName("com.bumptech.glide.load.resource.gif.GifFrameLoader");
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);
//設(shè)置只播放一次
resource.setLoopCount(1);
//獲得總幀數(shù)
int count = resource.getFrameCount();
int delay = 0;
for (int i = 0; i < count; i++) {
//計(jì)算每一幀所需要的時間進(jìn)行累加
delay += (int) getDelayMethod.invoke(gifDecoder, i);
}
imageView.postDelayed(new Runnable() {
@Override
public void run() {
if (gifListener != null) {
gifListener.gifPlayComplete();
}
}
}, 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 false;
}
}).into(imageView);
}
/**
* Gif播放完畢回調(diào)
*/
public interface GifListener {
void gifPlayComplete();
}
同時塘安,因?yàn)槲覀儾捎玫氖欠瓷洌詣e忘了在你的proguard-rules.pro
中加上Glide的反混淆規(guī)則援奢,
#Glide
-keep class com.bumptech.glide.** {*;}
好了兼犯,這樣就大功告成啦~
如果覺得對你有所幫助,請點(diǎn)個贊集漾,謝謝切黔。你的鼓勵是我最大的動力。
歡迎關(guān)注EoniJJ的簡書
不定期與你分享關(guān)于Android開發(fā)的點(diǎn)點(diǎn)滴滴具篇。