Glide: Allow a different scale type for placeholder images

Created on 13 Mar 2015  路  7Comments  路  Source: bumptech/glide

We want to have a placeholder image that looks a bit like a 'picture frame' icon - similar to what facebook does in their timeline. We want the final images to be show using centerCrop. However it seems that the centerCrop also gets applied to the placeholder making it way to large. It would be nice to have a way to set the placeholder scaling.

question

Most helpful comment

Aha! Thanks for the clarification, @sjudd . I originally used listener() and set the scale type in the listener's onException(), however your suggestion is better. I now use the following custom ImageViewTarget:

public class ScaleErrorImageViewTarget
    extends GlideDrawableImageViewTarget
{
    ScaleType mErrorScaleType;

    public ScaleErrorImageViewTarget(ImageView view, ScaleType errorScaleType) {
        super(view);
        mErrorScaleType = errorScaleType;
    }

    @Override
    public void onLoadFailed(Exception e, Drawable errorDrawable) {
        ImageView imageView = getView();
        imageView.setScaleType(mErrorScaleType);
        super.onLoadFailed(e, errorDrawable);
    }

    @NonNull
    public static ScaleErrorImageViewTarget errorCenter(ImageView imageView) {
        return new ScaleErrorImageViewTarget(imageView, ScaleType.CENTER);
    }
}

So, the example above becomes (with the proper static imports):

Glide.with(this)
     .load(uri)
     .centerCrop()
     .error(R.drawable.error_image)
     .into(errorCenter(imageView));

All 7 comments

Glide doesn't scale or transform placeholders, although the view you're displaying them in might. You might want to set the scale type on your view to whatever you want to use to scale your placeholder and then use a transformation in Glide to scale/crop your result.

If the ImageView belongs to a ListView item, it may be used for different images due to ListView's view recycling.
If the image is at first successfully loaded and we use centerCrop(), the ImageView's scaleType is changed to centerCrop. Later, if an error/placeholder image is set to the same ImageView, it will be loaded with that scaleType, not the original one.

So what is needed is:

  • the scaleType to be set everytime an image is loaded to the ImageView,
  • a way to define the scaleType for placeholder and error images

Example:

Glide.with(this)
     .load(uri)
     .centerCrop()
     .error(R.drawable.error_image)
     .errorFitCenter()
     .into(imageView);

Just to be clear, Glide doesn't currently set the scale type on the view. We do read from it to choose a default transformation if one isn't set manually, but the scale type on the view is never modified.

We could look in to doing what you suggest, but the generic nature of Target is going to make it somewhat difficult. You could however, definitely use a custom ImageViewTarget and change the scale type in onLoadStarted/Cleared/Ready to get the same effect.

Aha! Thanks for the clarification, @sjudd . I originally used listener() and set the scale type in the listener's onException(), however your suggestion is better. I now use the following custom ImageViewTarget:

public class ScaleErrorImageViewTarget
    extends GlideDrawableImageViewTarget
{
    ScaleType mErrorScaleType;

    public ScaleErrorImageViewTarget(ImageView view, ScaleType errorScaleType) {
        super(view);
        mErrorScaleType = errorScaleType;
    }

    @Override
    public void onLoadFailed(Exception e, Drawable errorDrawable) {
        ImageView imageView = getView();
        imageView.setScaleType(mErrorScaleType);
        super.onLoadFailed(e, errorDrawable);
    }

    @NonNull
    public static ScaleErrorImageViewTarget errorCenter(ImageView imageView) {
        return new ScaleErrorImageViewTarget(imageView, ScaleType.CENTER);
    }
}

So, the example above becomes (with the proper static imports):

Glide.with(this)
     .load(uri)
     .centerCrop()
     .error(R.drawable.error_image)
     .into(errorCenter(imageView));

Glad this is resolved, let us know if you have more questions!

Great solution!

But I faced two issues with your solution with custom GlideDrawableImageViewTarget when I use it in a GridView's adapter:

  1. I receive more calls to onLoadFailed() than actual failed images.
    for instance: my adapter loads 10 images, one of them is invalid (0 bytes) but I got 3 calls to onLoadFailed() method with two different messages. But 9 of 10 images are loaded correctly.

  2. The second and the most frustrating issue:
    In adapter all ImageViews have new scaleType. When I debug I can see that onLoadFailed() is called only three times, so I expect 3 imagviews to have updated scaleType. But actually they all are getting updated.

anyway your approach helped me, thanks man!

@karmazinkd
It would be great if you could share your solution here.

Was this page helpful?
0 / 5 - 0 ratings