Glide: Hidden ImageView becomes visible temporarily when loading image

Created on 1 Feb 2016  路  6Comments  路  Source: bumptech/glide

Glide Version: 3.6.x and 3.7.0
Device: Shield TV, Android 5.1 & AFTV, Android 4.2.2

When Glide loads an image into an ImageView that is either set to Invisible or Gone, the ImageView becomes visible for 2-3 seconds and then disappears again. The desired effect would be for the image to remain hidden until the visibility is explicitly changed

Glide load line:

Glide.with(this).load(url).skipMemoryCache(true).into(primaryImage);

"this" is a Fragment context

Layout XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:id="@+id/rlControlsContainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:paddingTop="@dimen/paddingRegular"
        android:paddingEnd="@dimen/paddingRegular"
        android:paddingBottom="@dimen/paddingRegular"
        android:paddingStart="140dp"
        android:background="@color/colorDarkUnderlay"
        android:visibility="gone">

        // removed content for readability

    </RelativeLayout>

    <ImageView
        android:id="@+id/ivPrimaryImage"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="@dimen/paddingLarge"
        android:layout_marginBottom="@dimen/paddingRegular"
        android:layout_alignParentBottom="true"
        android:visibility="invisible"/>    

</RelativeLayout>

Stack trace / LogCat:
Not crashing, no stacktrace

keywords: flashing, flashes, visibility, flicker, flickering

non-library question wontfix

Most helpful comment

Same issue for me.
Worked with:

Glide.with(context).load(iconUrl).into(new SimpleTarget<GlideDrawable>() {
    @Override
    public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
        icon.setImageDrawable(resource);
    }
});

All 6 comments

Same issue for me.
Worked with:

Glide.with(context).load(iconUrl).into(new SimpleTarget<GlideDrawable>() {
    @Override
    public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
        icon.setImageDrawable(resource);
    }
});

Same problem here.

Problem seems to be related with the crossFade animation as if you call dontAnimate or you set the imageview manually as @pengrad said all works correctly.

@pengrad's solution is really unsafe (clearing won't actually get rid of the resource), but it could be made safe if you replace SimpleTarget<GlideDrawable> with GlideDrawableImageViewTarget like this:

.into(new GlideDrawableImageViewTarget(imageView) {
    @Override public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {
        super.onResourceReady(resource, null); // ignores animation, but handles GIFs properly.
    }
});

This still works, because the workaround he found was actually just ignoring the glideAnimation; along with unimplementing all the goodies ImageViewTarget gives. Ignoring the animation in onResourceReady is equivalent to .dontAnimate(), which is a much cleaner well-communicated method call compared to a weird custom target.

@alexmiragall yes, .dontAnimate() is the best workaround for this. It shouldn't be even regarded as a workaround, but a solution, because there's no point in animating an image into an invisible view. Most of the time loading into an invisible view doesn't even work, because it has not been laid out and hence it doesn't have a size. Glide needs the size to start a load (this size could come from an eariler layout pass, or .override in case of non-visible views).

This still leaves the question of why an invisible view renders when animated. @RedshirtMB's 2-3 seconds sounds really weird, it should be more like 200-300 ms unless you called .crossFade(2500). In which case I can confirm that the view will become visible for the duration of the animation. But it is not a cross-fade (TransitionDrawable) animation, instead it's a fade in (AlphaAnimation), because there's no previous drawable (e.g. placeholder/thumbnail) to animate from (see DrawableCrossFadeViewAnimation.animate). The culprit is here:

public abstract class ViewGroup extends View {
    ...
    @Override protected void dispatchDraw(Canvas canvas) {
            ...
            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
                more |= drawChild(canvas, child, drawingTime);
            }

I think we can safely say that loading an image to non-visible view is an edge case, that is it's not covered by the defaults where .crossFade() is enabled, and adding .dontAnimate() is the way to go.

@TWiStErRob The GlideDrawable is not available anymore. What should I use instead?

@AndroidDeveloperLB I think it's simply Drawable and DrawableImageViewTarget. Consider using .dontAnimate() as well (if (view.getVisibility() == INVISIBLE)). Make sure you read and understand my comment about culprits of loading into invisible views, it is always applicable, even when using custom target.

@TWiStErRob I've found this thread because I wish to set an ImageView to be visible only if Glide got an image for it (gone otherwise). I'm not sure what you mean, but maybe this can do it safely:

                    imageView.visibility = View.GONE
                    if (!TextUtils.isEmpty(imageUrl))
                        Glide.with(activity).asBitmap().load(imageUrl).apply(RequestOptions.centerCropTransform())
                                .into(object : BitmapImageViewTarget(imageView) {
                                    override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
                                        super.onResourceReady(resource, transition)
                                        imageView.visibility = View.VISIBLE
                                    }
                                })

?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

FooBarBacon picture FooBarBacon  路  3Comments

sergeyfitis picture sergeyfitis  路  3Comments

AndroidJohnsonWang picture AndroidJohnsonWang  路  3Comments

PatrickMA picture PatrickMA  路  3Comments

kooeasy picture kooeasy  路  3Comments