I have one GIF image and want to load in Splash Screen. I came across few libraries like android-gif-drawable and Glide
Is there any way I can listen for one animation cycle complete ? I mean once animation cycle is complete(whole animation is completed, without repeating) I want a listener, that Animation is complete, and provides us with some callback. Somewhat like:
SomeLibrary.load("GIF")
.into(imageview)
.repeat(false)
.setOnAnimationCompleteListener(new OnAnimationCompleteListener(){
public void onAnimationComplete(){
// Animation is completed. Do whatever you want to do..
}
});
I have worked with both libraries But looking for a feature as I mentioned above.
For Glide V4 I've found this to be the best answer. https://github.com/bumptech/glide/pull/3438
Glide.with(this).asGif().load(/*your gif url*/).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) {
resource.setLoopCount(1);
resource.registerAnimationCallback(new Animatable2Compat.AnimationCallback() {
@Override
public void onAnimationEnd(Drawable drawable) {
//do whatever after specified number of loops complete
}
});
return false;
}
}).into(imageView);
Update 2018/9/25 After a long period of use in this code
I found that some phones did not really start running in onResourceReady
. Means that I get isRunning() == false
once onResourceReady
is called.
Solution: Sleeping at the beginning.
@Override
public boolean onResourceReady(final GifDrawable resource, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {
resource.setLoopCount(1);
new Thread(new Runnable() {
@Override
public void run() {
Thread.sleep(200);
while(true) {
if(!resource.isRunning()) {
onGifFinished();//do your stuff
break;
}
}
}
}).start();
return false;
}
Origin
Because the GIF has a delay when playing, I use the thread to monitor the end of the play. Not a very good but effective way.
Glide.with(this).asGif().load(R.raw.gif)
.apply(RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.NONE)).listener(new RequestListener<GifDrawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<GifDrawable> target, boolean isFirstResource) {
onGifFinished();//do your stuff
return false;
}
@Override
public boolean onResourceReady(final GifDrawable resource, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {
resource.setLoopCount(1);
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
if(!resource.isRunning()) {
onGifFinished();//do your stuff
break;
}
}
}
}).start();
return false;
}
}).into(iv);
Below is the complete code for gif 1 loop animation. After completing loop, control will redirects to next activity.
private void initGlideGifImageView() {
showProgressDialog("Loading image...");
GlideDrawableImageViewTarget imageViewTarget = new GlideDrawableImageViewTarget(imgSafetyGif, 1);
Glide
.with(this)
.load(GIF_SOURCE_URL)
.placeholder(R.drawable.img_placeholder_1)
.error(R.drawable.img_error_1_280_text)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.listener(new RequestListener<String, GlideDrawable>() {
@Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
hideProgressDialog();
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
hideProgressDialog();
GifDrawable gifDrawable = null;
Handler handler = new Handler();
if (resource instanceof GifDrawable) {
gifDrawable = (GifDrawable) resource;
int duration = 0;
GifDecoder decoder = gifDrawable.getDecoder();
for (int i = 0; i < gifDrawable.getFrameCount(); i++) {
duration += decoder.getDelay(i);
}
handler.postDelayed(new Runnable() {
@Override
public void run() {
Intent intent = new Intent(SplashScreenActivity.this, MainActivity.class);
startActivity(intent);
SplashScreenActivity.this.finish();
}
}, (duration + 3000));
}
return false;
}
})
.into(imageViewTarget);
}
I came a little bit late. I am going to improve the answer of @Codus.
@Override
public boolean onResourceReady(GifDrawable resource, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {
resource.setLoopCount(1);
resource.registerAnimationCallback(new CustomAnimationCallback() {
@Override
public void onEnd(Drawable drawable) {
}
});
return false;
}
And the CustomAnimationCallback()
public abstract class CustomAnimationCallback extends Animatable2Compat.AnimationCallback {
@Override
public void onAnimationStart(Drawable drawable)
{
onStart(drawable);
}
@Override
public void onAnimationEnd(Drawable drawable)
{
onEnd(drawable);
}
public abstract void onStart(Drawable drawable);
public abstract void onEnd(Drawable drawable);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With