bumptech / glide

An image loading and caching library for Android focused on smooth scrolling
https://bumptech.github.io/glide/
Other
34.59k stars 6.12k forks source link

Restarting from first frame shows frame from previous run #4144

Open BrainCrumbz opened 4 years ago

BrainCrumbz commented 4 years ago

Glide Version: 4.11.0

Integration libraries: None

Device/Android Version:

Issue details / Repro steps / Use case background: Issue details:
When a Gif animation is started, then stopped, then restarted from its first frame, the animation does not cleanly start from first frame. Instead, for a split second one can see the last shown frame from previous run.
This is visible very very frequently, although not systematically. To be sure of what you see, it helps to capture a screen recording and then moving with a time slider in it.
Basically it seems the same issue experienced here by @Elliptica1 user, but no answer found there. Checked also issue #3445 , but no help from there as well.

Repro steps: A repro project showing the issue is downloadable here.

  1. Press Show button to play the composed animation: intro starts from fully transparent area, then seamlessly joins with loop.
  2. After some seconds press Hide.
  3. Then again, press Show and you should see the intro starting from its last shown frame (the large circle, instead of fully transparent area). The loop as well might start from its last shown frame (you see a glitch between the intro and the loop, instead of a seamless joint).

You can repeat the process multiple times. The intro and loop parts have been visually marked with a dot in order to detect which is currently showing. Again, a screen recording helps. Here's an example.

Use case background:
To show (upon some event) a composed animation made by an intro GIF, played once, then followed by a looping GIF which keeps playing.
At some point (due to some event), looping animation will be stopped and hidden.
Later on, the same composed animation is started again, so first the intro plays from the beginning, then the loop plays from its beginning. Intro animation must always start from its first frame, as well as loop animation must always start from its first frame, in order to give a visually seamless effect.
For sake of simplicity, repro project does not include fade, cross-fade and other effects that we might apply in our actual use case.

Glide load line:
Repro project here contains actual used code.

        RequestManager requestManager = Glide.with(context.getApplicationContext());

        loopTarget = new MyCustomTarget(loopImageView, true, null);

        requestManager
                .asGif()
                .load(LOOP_RES_ID)
                .into(loopTarget);

/*
class MyCustomTarget extends ImageViewTarget<GifDrawable>
- stops resource, to prevent autoplay
- sets either 1 or infinite loop count
- registers animation callback, if any
*/

GlideModule:

@GlideModule
public class RestartGifAppGlideModule extends AppGlideModule {
    // needed for Glide library
}

Layout XML: Repro project here contains actual used code.

    <FrameLayout
        android:id="@+id/frameLayout"
        android:layout_width="409dp"
        android:layout_height="649dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/showButton">

ImageViews are added programmatically:

    private static int IMAGE_WIDTH = 750;
    private static int IMAGE_HEIGHT = 750;

// upon activity onStart event:

        loopImageView = new ImageView(context);
        loopImageView.setTag("Loop");

        loopImageView.setVisibility(View.GONE);
        frameLayout.addView(loopImageView);

// upon frameLayout first onLayoutChange event:

        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(IMAGE_WIDTH, IMAGE_HEIGHT);

        // center in container
        layoutParams.leftMargin = (frameLayout.getWidth() - IMAGE_WIDTH) / 2;
        layoutParams.topMargin = (frameLayout.getHeight() - IMAGE_HEIGHT) / 2;
        layoutParams.rightMargin = 0;
        layoutParams.bottomMargin = 0;

        loopImageView.setLayoutParams(layoutParams);

Stack trace / LogCat: There's no logged error involved.

BrainCrumbz commented 3 years ago

Does anyone know if there's been any improvement on this behaviour? Maybe with more recent Glide versions?
TA