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.
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:
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:
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.
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.
Most helpful comment
Aha! Thanks for the clarification, @sjudd . I originally used
listener()and set the scale type in the listener'sonException(), however your suggestion is better. I now use the following customImageViewTarget:So, the example above becomes (with the proper static imports):