|
14 | 14 | import android.graphics.drawable.Drawable;
|
15 | 15 | import android.support.annotation.NonNull;
|
16 | 16 | import android.support.annotation.VisibleForTesting;
|
| 17 | +import android.support.graphics.drawable.Animatable2Compat; |
17 | 18 | import android.view.Gravity;
|
18 | 19 | import com.bumptech.glide.Glide;
|
19 | 20 | import com.bumptech.glide.gifdecoder.GifDecoder;
|
20 | 21 | import com.bumptech.glide.load.Transformation;
|
21 | 22 | import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
|
22 | 23 | import com.bumptech.glide.util.Preconditions;
|
23 | 24 | import java.nio.ByteBuffer;
|
| 25 | +import java.util.ArrayList; |
| 26 | +import java.util.List; |
24 | 27 |
|
25 | 28 | /**
|
26 | 29 | * An animated {@link android.graphics.drawable.Drawable} that plays the frames of an animated GIF.
|
27 | 30 | */
|
28 | 31 | public class GifDrawable extends Drawable implements GifFrameLoader.FrameCallback,
|
29 |
| - Animatable { |
| 32 | + Animatable, Animatable2Compat { |
30 | 33 | /**
|
31 | 34 | * A constant indicating that an animated drawable should loop continuously.
|
32 | 35 | */
|
@@ -76,6 +79,11 @@ public class GifDrawable extends Drawable implements GifFrameLoader.FrameCallbac
|
76 | 79 | private Paint paint;
|
77 | 80 | private Rect destRect;
|
78 | 81 |
|
| 82 | + /** |
| 83 | + * Callbacks to notify loop completion of a gif, where the loop count is explicitly specified. |
| 84 | + */ |
| 85 | + private List<AnimationCallback> animationCallbacks; |
| 86 | + |
79 | 87 | /**
|
80 | 88 | * Constructor for GifDrawable.
|
81 | 89 | *
|
@@ -351,10 +359,19 @@ public void onFrameReady() {
|
351 | 359 | }
|
352 | 360 |
|
353 | 361 | if (maxLoopCount != LOOP_FOREVER && loopCount >= maxLoopCount) {
|
| 362 | + notifyAnimationEndToListeners(); |
354 | 363 | stop();
|
355 | 364 | }
|
356 | 365 | }
|
357 | 366 |
|
| 367 | + private void notifyAnimationEndToListeners() { |
| 368 | + if (animationCallbacks != null) { |
| 369 | + for (int i = 0, size = animationCallbacks.size(); i < size; i++) { |
| 370 | + animationCallbacks.get(i).onAnimationEnd(this); |
| 371 | + } |
| 372 | + } |
| 373 | + } |
| 374 | + |
358 | 375 | @Override
|
359 | 376 | public ConstantState getConstantState() {
|
360 | 377 | return state;
|
@@ -390,6 +407,42 @@ public void setLoopCount(int loopCount) {
|
390 | 407 | }
|
391 | 408 | }
|
392 | 409 |
|
| 410 | + /** |
| 411 | + * Register callback to listen to GifDrawable animation end event after specific loop count |
| 412 | + * set by {@link GifDrawable#setLoopCount(int)}. |
| 413 | + * |
| 414 | + * Note: This will only be called if the Gif stop because it reaches the loop count. Unregister |
| 415 | + * this in onLoadCleared to avoid potential memory leak. |
| 416 | + * @see GifDrawable#unregisterAnimationCallback(AnimationCallback). |
| 417 | + * |
| 418 | + * @param animationCallback Animation callback {@link Animatable2Compat.AnimationCallback}. |
| 419 | + */ |
| 420 | + @Override |
| 421 | + public void registerAnimationCallback(@NonNull AnimationCallback animationCallback) { |
| 422 | + if (animationCallback == null) { |
| 423 | + return; |
| 424 | + } |
| 425 | + if (animationCallbacks == null) { |
| 426 | + animationCallbacks = new ArrayList<>(); |
| 427 | + } |
| 428 | + animationCallbacks.add(animationCallback); |
| 429 | + } |
| 430 | + |
| 431 | + @Override |
| 432 | + public boolean unregisterAnimationCallback(@NonNull AnimationCallback animationCallback) { |
| 433 | + if (animationCallbacks == null || animationCallback == null) { |
| 434 | + return false; |
| 435 | + } |
| 436 | + return animationCallbacks.remove(animationCallback); |
| 437 | + } |
| 438 | + |
| 439 | + @Override |
| 440 | + public void clearAnimationCallbacks() { |
| 441 | + if (animationCallbacks != null) { |
| 442 | + animationCallbacks.clear(); |
| 443 | + } |
| 444 | + } |
| 445 | + |
393 | 446 | static final class GifState extends ConstantState {
|
394 | 447 | @VisibleForTesting
|
395 | 448 | final GifFrameLoader frameLoader;
|
|
0 commit comments