在Glide3.0的时候,我们可以通过GifDecoder获取每一帧的播放时长然后相加得到gif的播放时长,即:
GifDrawable drawable = (GifDrawable) glideDrawable;
GifDecoder decoder = drawable.getDecoder();
long duration = 0;
for (int i = 0; i < drawable.getFrameCount(); i++) {
duration += decoder.getDelay(i);
}
然后使用handle 发送一个延时消息,或者其它方法,等gif播放完成以后再做相应操作。
或者,通过重写GifDrawable,重写onStop()方法来处理:
public class MyGifDrawable extends GifDrawable {
public MyGifDrawable (GifDrawable other) {
this(other, other.getFirstFrame(), other.getFrameTransformation());
}
@Override
public void stop() {
super.stop();
//GIF播放完成,可以做一些操作
}
}
但是到Glide4.0, GifDecoder 被声明为private,去掉了getDecoder()方法,第一种方法如果不使用反射,是无法做到的。
这时我们可以去重写GifDrawable,MyGifDrawable 继承自GifDrawable,然后我们去获GifDrawable里边存储的gif的数据,然后重新初始化一个GifDecoder,使用这个GifDecoder重新new 一个MyGifDrawable ,在MyGifDrawable 的stop方法中监听gif播放完成的时机。
public class MyGifDrawable extends GifDrawable {
public MyGifDrawable (Context context, GifDecoder bitmapProvider, Transformation<Bitmap> frameTransformation, int targetFrameWidth, int targetFrameHeight, Bitmap firstFrame) {
super(context, bitmapProvider, frameTransformation, targetFrameWidth, targetFrameHeight, firstFrame);
}
@Override
public void stop() {
super.stop();
//这里之所以要判断callBack是否为null,是因为在RecycleView中当gif划出屏幕,然后再划入屏幕时,callback会为null,
//在GifDrawable中的onFrameReady()方法,会判断如果callback为null,会直接会调用onstop方法,当gif图在recycleview中,划出//屏幕再划入屏幕时,callback会为null,这是就会出现,当第一帧刚准备好显示出来,就会马上调用onstop()方法,为避免这种情况,在此加入//下方这个判断。
if (getCallback() != null) {
//GIF播放完成,可以做一些操作
}
}
}
可以在Glide的RequestListener中的onResourceReady中拿到glide解析好的gifDrawable,来调用以下方法初始化我们自己定义的GifDrawable
public static MyGifDrawable initMyGifDrawable(Context context, GifDrawable gifDrawable) {
GifBitmapProvider provider = new GifBitmapProvider(Glide.get(context).getBitmapPool());
Transformation transformation = gifDrawable.getFrameTransformation();
if (transformation == null) {
transformation = new CenterCrop();
}
ByteBuffer byteBuffer = gifDrawable.getBuffer();
StandardGifDecoder decoder = new StandardGifDecoder(provider);
decoder.setData(new GifHeaderParser().setData(byteBuffer).parseHeader(),byteBuffer);
Bitmap bitmap = gifDrawable.getFirstFrame();
if (bitmap == null) {
decoder.advance();
bitmap = decoder.getNextFrame();
}
return new MyGifDrawable(context, decoder, transformation, 0, 0, bitmap);
}
当然也可以使用以下方法来通过Glide拿到图片的二进制数组,来初始化MyGifDrawable :
// target.get() 必须放到子线程中执行,方法中未做处理,所以此方法必须在子线程中执行
public static MyGifDrawable loadGif(final Context context, final String url, final RequestOptions options) {
byte[] data = null;
FutureTarget<byte[]> target = Glide.with(context)
.as(byte[].class)
.load(url)
.apply(options)
.into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
try {
data = target.get();
} catch (Exception e) {
e.printStackTrace();
}
return initMyGifDrawable(context, data);
}
public static MyGifDrawable initMyGifDrawable(Context context, byte[] data) {
if (data == null) {
return null;
}
GifBitmapProvider provider = new GifBitmapProvider(Glide.get(context).getBitmapPool());
Transformation transformation = new CenterCrop();
StandardGifDecoder decoder = new StandardGifDecoder(provider);
decoder.read(data);
decoder.advance();
Bitmap bitmap = decoder.getNextFrame();
return new MyGifDrawable(context, decoder, transformation, 0, 0, bitmap);
}
最后拿到MyGifDrawable的对象后,可以调用setLoopCount() 来设置循环次数,调用start()方法开始gif的播放