Fading animation not working when an image is loaded with .asBitmap() - android

I have this code
Glide
.with(this)
.load(mUrl)
.asBitmap()
.thumbnail(Glide
.with(this)
.load(mPreviewUrl)
.asBitmap()
.animate(R.anim.fade_in))
.listener(new RequestListener<String, Bitmap>() {
#Override
public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {
mProgressBar.setVisibility(View.GONE);
return false;
}
#Override
public boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {
mProgressBar.setVisibility(View.GONE);
return false;
}
})
.into(new SimpleTarget<Bitmap>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
#Override
public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
mWallpaperImageView.setImageBitmap(resource);
createPaletteAsync(resource);
}
});
This downloads an image and returns a Bitmap object, which then I use to generate a palette of colour with the Palette library. I also want to load the bitmap in an ImageView, and I do that with mWallpaperImageView.setImageBitmap(resource) which loads the image without any fading or animation to smooth out the loading.
If I use glide like this:
Glide.with(this)
.load(mUrl)
.crossFade(500)
.into(mImageView)
then the image appears with fading but then I don't have a Bitmap object.

According to this answer,
Unfortunately, there isn't a built in way to cross fade Bitmaps. You
can however, use a custom BitmapImageViewTarget, and use a
TransitionDrawable in onResourceReady() to cross fade.
Fortunately, there's a trick to enable fading effect with bitmap in Glide.
For this you will need two classes,
FadingDrawable
final public class FadingDrawable extends BitmapDrawable {
// Only accessed from main thread.
private static final float FADE_DURATION = 200; //ms
private final float density;
Drawable placeholder;
long startTimeMillis;
boolean animating;
int alpha = 0xFF;
FadingDrawable(Context context, Bitmap bitmap, Drawable placeholder) {
super(context.getResources(), bitmap);
this.density = context.getResources().getDisplayMetrics().density;
this.placeholder = placeholder;
animating = true;
startTimeMillis = SystemClock.uptimeMillis();
}
/**
* Create or update the drawable on the target {#link android.widget.ImageView} to display the supplied bitmap
* image.
*/
static public void setBitmap(ImageView target, Context context, Bitmap bitmap) {
if (bitmap != null && !bitmap.isRecycled()) {
Drawable placeholder = target.getDrawable();
if (placeholder instanceof AnimationDrawable) {
((AnimationDrawable) placeholder).stop();
}
FadingDrawable drawable = new FadingDrawable(context, bitmap, placeholder);
//this will avoid OverDraw
//target.setBackgroundDrawable(null);
//target.setBackgroundColor(0);
target.setImageDrawable(drawable);
}
}
/**
* Create or update the drawable on the target {#link android.widget.ImageView} to display the supplied
* placeholder image.
*/
static void setPlaceholder(ImageView target, Drawable placeholderDrawable) {
target.setImageDrawable(placeholderDrawable);
if (target.getDrawable() instanceof AnimationDrawable) {
((AnimationDrawable) target.getDrawable()).start();
}
}
#Override
public void draw(Canvas canvas) {
if (!animating) {
super.draw(canvas);
} else {
float normalized = (SystemClock.uptimeMillis() - startTimeMillis) / FADE_DURATION;
if (normalized >= 1f) {
animating = false;
placeholder = null;
super.draw(canvas);
} else {
if (placeholder != null) {
placeholder.draw(canvas);
}
int partialAlpha = (int) (alpha * normalized);
super.setAlpha(partialAlpha);
super.draw(canvas);
super.setAlpha(alpha);
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
invalidateSelf();
}
}
}
}
#Override
public void setAlpha(int alpha) {
this.alpha = alpha;
if (placeholder != null) {
placeholder.setAlpha(alpha);
}
super.setAlpha(alpha);
}
#Override
public void setColorFilter(ColorFilter cf) {
if (placeholder != null) {
placeholder.setColorFilter(cf);
}
super.setColorFilter(cf);
}
#Override
protected void onBoundsChange(Rect bounds) {
if (placeholder != null) {
placeholder.setBounds(bounds);
}
super.onBoundsChange(bounds);
}
}
and GlideImageView
public class GlideImageView extends AppCompatImageView {
public GlideImageView(Context context) {
this(context, null);
}
public GlideImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public GlideImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
Drawable placeholder = getDrawable();
if (placeholder instanceof AnimationDrawable) {
((AnimationDrawable) placeholder).stop();
Glide.clear(this);
}
}
#Override
public void setImageBitmap(Bitmap bitmap) {
if (bitmap != null) FadingDrawable.setBitmap(this, getContext(), bitmap);
}
public void setImageBitmapWithoutAnimation(Bitmap bitmap) {
super.setImageBitmap(bitmap);
}
}
Now change your mWallpaperImageView from ImageView to
<com.yourpackage.GlideImageView
android:id="#+id/mWallpaperImageView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
And finally remove all external animation effect from Glide configuration,
Glide
.with(this)
.load(mUrl)
.asBitmap()
.thumbnail(Glide
.with(this)
.load(mPreviewUrl)
.asBitmap()
.listener(new RequestListener<String, Bitmap>() {
#Override
public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {
mProgressBar.setVisibility(View.GONE);
return false;
}
#Override
public boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {
mProgressBar.setVisibility(View.GONE);
return false;
}
})
.into(new SimpleTarget<Bitmap>(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) {
#Override
public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
mWallpaperImageView.setImageBitmap(resource);
createPaletteAsync(resource);
}
});
Tested and working properly!

You can use the value of the alpha of an image to create a fade in or fade out effect:
In Java
yourimage.animate().setAlpha(0f).setDuration(2000);
given that the image's alpha starts with alpha =1 (not transparent).
so the image will disappear (transparent) during 2 seconds

Related

How to save/read inline images in html content to internal/extrenal memory

According to this question I used a custom ImageGatter class to display images that I'm getting from a server in TextView using Picasso
public class PicassoImageGetter implements Html.ImageGetter {
private TextView textView = null;
Context mContext;
public PicassoImageGetter() {
}
public PicassoImageGetter(TextView target, Context context) {
textView = target;
mContext = context;
}
#Override
public Drawable getDrawable(String source) {
BitmapDrawablePlaceHolder drawable = new BitmapDrawablePlaceHolder();
Picasso.get().load(source).into(drawable);
return drawable;
}
private class BitmapDrawablePlaceHolder extends BitmapDrawable implements com.squareup.picasso.Target {
protected Drawable drawable;
#Override
public void draw(final Canvas canvas) {
if (drawable != null) {
drawable.draw(canvas);
}
}
public void setDrawable(Drawable drawable) {
this.drawable = drawable;
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
drawable.setBounds(0, 0, width, height);
setBounds(0, 0, width, height);
if (textView != null) {
textView.setText(textView.getText());
}
}
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
setDrawable(new BitmapDrawable(mContext.getResources(), bitmap));
}
#Override
public void onBitmapFailed(Exception e, Drawable errorDrawable) {
setDrawable(errorDrawable);
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
}
}
and used like this
imageGetter = new PicassoImageGetter(contentTextView, this);
Spannable html;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
html = (Spannable) Html.fromHtml(content, Html.FROM_HTML_MODE_LEGACY, imageGetter, null);
} else {
html = (Spannable) Html.fromHtml(content, imageGetter, null);
}
contentTextView.setText(html);
I need to catch this images into internal or external storage to display it if there's no connection, but I don't know the path or file name.
You need to implement picasso cache by your own. This should be like this:
public class PicassoCache {
private static Picasso picassoInstance = null;
private PicassoCache(Context context) {
Downloader downloader = new OkHttp3Downloader(context, Integer.MAX_VALUE);
Picasso.Builder builder = new Picasso.Builder(context);
builder.downloader(downloader);
picassoInstance = builder.build();
}
public static Picasso getPicassoInstance(Context context) {
if (picassoInstance == null) {
new PicassoCache(context);
return picassoInstance;
}
return picassoInstance;
}
}
Then in your code:
#Override
public Drawable getDrawable(String source) {
BitmapDrawablePlaceHolder drawable = new BitmapDrawablePlaceHolder();
PicassoCache.getPicassoInstance(getContext()).load(source).into(drawable);
return drawable;
}
OkHttp3Downloader will install an image cache into your application cache directory. You can also use another constructor with your own provided directory public OkHttp3Downloader(final File cacheDir, final long maxSize)
As an alternative, you can use Glide. This is like picasso but also allows you to show gifs with animation and cache strategy IMHO is a bit easier.
Glide.with(context)
.load(source)
.apply(RequestOptions().diskCacheStrategy(DiskCacheStrategy.ALL))
.into(drawable)

Glide loader is not loading image properly

I am using Glide loader to load my images. My code is working but it changes images continuously. Here is my code:
Glide.with(ctx).load(image).asBitmap()
.dontTransform()
.placeholder(R.drawable.cart)
.into(new SimpleTarget < Bitmap > () {
#Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
photoImageView.setImageBitmap(resource);
Glide.with(ctx).load(image).into(post_image);
post_image.setImageBitmap(resource);
}
Hey You can use glide utill class for better understanding
public class GlideUtil {
public static void loadImage(String url, ImageView imageView) {
Context context = imageView.getContext();
if(context!=null || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)) {
assert context != null;
ColorDrawable cd = new ColorDrawable(ContextCompat.getColor(context, R.color.blue_grey_500));
Glide.with(context)
.load(url)
.placeholder(cd)
.crossFade()
.centerCrop()
.into(imageView);
}
}
public static void loadProfileIcon(String url, ImageView imageView) {
Context context = imageView.getContext();
if(context!=null || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)) {
Glide.with(context)
.load(url)
.placeholder(R.drawable.ic_person_outline_black)
.dontAnimate()
.fitCenter()
.into(imageView);
}
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public static void loadImage(String url, ImageView mPhotoView, final ProgressBar mProgress) {
Context context = mPhotoView.getContext();
if(context!=null || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)) {
assert context != null;
ColorDrawable cd = new ColorDrawable(ContextCompat.getColor(context, R.color.blue_grey_500));
mProgress.setEnabled(true);
Glide.with(context)
.load(url)
.listener(new RequestListener<String, GlideDrawable>() {
#Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
mProgress.setVisibility(View.GONE);
return false;
}
#Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
mProgress.setVisibility(View.GONE);
return false;
}
})
.placeholder(cd)
.crossFade()
.centerCrop()
.into(mPhotoView);
}
}
}
Image changing occurs because of lazy loading of images in the glide. When the glide is downloading the new image previous image will be already loaded since you are reusing the view. To prevent this,.Before loading images clear the previous image before loading image.
Glide.clear(post_image);
EDIT:
Also before fetching the image from glide clear the old image of the imageView.
post_image.setImageDrawable(null);
Then load the new image from glide
Glide.with(ctx)
.load(image)
.asBitmap()
.dontTransform()
.placeholder(R.drawable.cart)
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
post_image.setImageBitmap(resource);
}
}

Glide: onError Callback

I'm switching from Picasso to Glide. Everything works fine except I cannot find a method to get an error callback. I want to retrieve a Bitmap, pass it on and generate an Android Palette from it. Also, while an errorDrawable can be provided to a load call, it won't show up in onResourceReady when using a SimpleTarget.
In Picasso I did it like this:
target = new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
//handle Bitmap, generate Palette etc.
}
#Override
public void onBitmapFailed(final Drawable errorDrawable) {
// use errorDrawable to generate Palette
}
#Override
public void onPrepareLoad(final Drawable placeHolderDrawable) {
}
};
int width = (int) DisplayUnitsConverter.dpToPx(this, 120);
int height = (int) DisplayUnitsConverter.dpToPx(this, 40);
Picasso.with(this).load(config.getPathToLogo()).resize(width, height).error(errorDrawableId).into(target);
My glide code looks like this:
Glide.with(context)
.load(config.getPathToLogo())
.asBitmap()
.into(new SimpleTarget<Bitmap>(width, height) {
#Override
public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
//handle Bitmap, generate Palette etc.
}
});
Thanks.
For everyone with the same problem - you need to use listener method. For example:
Glide.with(activity)
.load(getPhoto().getUrl())
.apply(
new RequestOptions()
.error(R.drawable.icon_placeholder)
.centerCrop()
)
.listener(new RequestListener<Drawable>() {
#Override
public boolean onLoadFailed(#Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
//on load failed
return false;
}
#Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
//on load success
return false;
}
})
.transition(withCrossFade())
.into(view);
You are using SimpleTarget that implements the interface Target that defines the method onLoadFailed so you only need to do:
Glide.with(context)
.load(config.getPathToLogo())
.asBitmap()
.into(new SimpleTarget<Bitmap>(width, height) {
#Override
public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) {
//handle Bitmap, generate Palette etc.
}
#Override
public void onLoadFailed(Exception e, Drawable errorDrawable) {
// Do something.
}
});

set add background color to glide image

I'm using Glide for setting png images (with transparencies) in ImageView in this mode:
Glide.with(context).load(url)
.crossFade()
.placeholder(R.drawable.no_contest)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into((ImageView)container);
Is it possible to set the backgroundcolor of the image without setting the background color of ImageView ?
thanks
LayerDrawable should be used:
.into(new SimpleTarget<GlideDrawable>() {
#Override
public void onResourceReady(GlideDrawable resource,
GlideAnimation<? super GlideDrawable> glideAnimation) {
final ShapeDrawable background = new ShapeDrawable();
background.getPaint().setColor("color here");
final Drawable[] layers = {background, resource};
container.setImageDrawable(new LayerDrawable(layers));
}
});
This will set background color according to your gif.
Glide code:
Glide.with(context).load(newspojo.getImageLink())
.asGif()
.listener(new RequestListener<String, GifDrawable>() {
#Override
public boolean onException(Exception e, String model, Target<GifDrawable> target, boolean isFirstResource) {
return false;
}
#Override
public boolean onResourceReady(GifDrawable resource, String model, Target<GifDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
final Pojo pojo = new Pojo();
final GifDrawable resources = resource;
Palette.from(resource.getFirstFrame()).generate(new Palette.PaletteAsyncListener() {
#Override
public void onGenerated(#NonNull Palette palette) {
if (pojo.getPosterPalette() != null) {
setUpInfoBackgroundColor(holder.ivRow, palette);
} else {
Palette.from(resources.getFirstFrame()).generate(new Palette.PaletteAsyncListener() {
public void onGenerated(Palette palette) {
pojo.setPosterPalette(palette);
setUpInfoBackgroundColor(holder.ivRow, palette);
}
});
}
}
});
return false;
}
})
.into(holder.ivRow);
}
Here is Pojo:
public class Pojo {
public Palette posterPalette;
public Palette getPosterPalette() {
return posterPalette;
}
public void setPosterPalette(Palette posterPalette) {
this.posterPalette = posterPalette;
}
public Pojo(){
}
}
and add in build.gradle:
implementation 'com.android.support:palette-v7:27.1.1'

Using Picasso with Image Getter

I ma building a chat application and I am attempting to append an image to an EditText, through use of Picasso to get the image from a URL and the append and ImageGetter to attach the image to the EditText. However, what I have implemented below does not work, as appending messages when using the app displays nothing (but the message does show up in the database).
I have tested without using Picasso, as simply just using the ImageGetter with an image resource within the app works just fine, only it's not from a URL as is required.
What is the proper way to configure the ImageGetter and/or the append method so that this functionality will work with Picasso? Or is there a simpler way?
Append method:
public void appendToMessageHistory(final String username,
final String message) {
if (username != null && message != null) {
Picasso.with(getBaseContext())
.load("http://localhost:3000/uploads/campaign/image/2/2.jpg")
.into(new Target() {
#Override
public void onPrepareLoad(Drawable arg0) {
}
#Override
public void onBitmapLoaded(Bitmap bitmap,
LoadedFrom arg1) {
Drawable drawImage = new BitmapDrawable(
getBaseContext().getResources(), bitmap);
drawImage.setBounds(0, 0,
drawImage.getIntrinsicHeight(),
drawImage.getIntrinsicWidth());
messageHistoryText.append(Html.fromHtml("<b>"
+ username + ":" + "</b>" + "<br>"));
messageHistoryText.append(Html.fromHtml(message
+ "<hr>" + "<br>")
+ System.getProperty("line.separator") + "");
messageHistoryText.append(Html
.fromHtml("<img src = '" + drawImage
+ "'/>",
imageGetter,
null));
}
#Override
public void onBitmapFailed(Drawable arg0) {
}
});
}
}
ImageGetter:
ImageGetter imageGetter = new ImageGetter() {
Drawable imageUsed=null;
#Override
public Drawable getDrawable(String source) {
Picasso.with(getBaseContext())
.load("http://localhost:3000/uploads/campaign/image/2/2.jpg")
.into(new Target() {
#Override
public void onPrepareLoad(Drawable arg0) {
}
#Override
public void onBitmapLoaded(Bitmap bitmap,
LoadedFrom arg1) {
Drawable drawImage = new BitmapDrawable(
getBaseContext().getResources(), bitmap);
drawImage.setBounds(0, 0,
drawImage.getIntrinsicHeight(),
drawImage.getIntrinsicWidth());
imageUsed=drawImage;
}
#Override
public void onBitmapFailed(Drawable arg0) {
}
});
return imageUsed;
}
};
I couldn't get it to work with using Picasso's Target...
My workaround is:
use an AsyncTask for concurrency
use Picasso's get() method to load the image synchronously in the AsyncTask's background method
Like this:
public class PicassoImageGetter implements Html.ImageGetter {
final Resources resources;
final Picasso pablo;
final TextView textView;
public PicassoImageGetter(final TextView textView, final Resources resources, final Picasso pablo) {
this.textView = textView;
this.resources = resources;
this.pablo = pablo;
}
#Override public Drawable getDrawable(final String source) {
final BitmapDrawablePlaceHolder result = new BitmapDrawablePlaceHolder();
new AsyncTask<Void, Void, Bitmap>() {
#Override
protected Bitmap doInBackground(final Void... meh) {
try {
return pablo.load(source).get();
} catch (Exception e) {
return null;
}
}
#Override
protected void onPostExecute(final Bitmap bitmap) {
try {
final BitmapDrawable drawable = new BitmapDrawable(resources, bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
result.setDrawable(drawable);
result.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
textView.setText(textView.getText()); // invalidate() doesn't work correctly...
} catch (Exception e) {
/* nom nom nom*/
}
}
}.execute((Void) null);
return result;
}
static class BitmapDrawablePlaceHolder extends BitmapDrawable {
protected Drawable drawable;
#Override
public void draw(final Canvas canvas) {
if (drawable != null) {
drawable.draw(canvas);
}
}
public void setDrawable(Drawable drawable) {
this.drawable = drawable;
}
}
Hope this is useful.
I built upon Thomas' answer. I used the existing Picasso methods to download any images on a different thread and accounted for the placeholder Drawables as well.
public class PicassoImageGetter implements Html.ImageGetter {
private TextView textView = null;
public PicassoImageGetter() {}
public PicassoImageGetter(TextView target) {
textView = target;
}
#Override
public Drawable getDrawable(String source) {
BitmapDrawablePlaceHolder drawable = new BitmapDrawablePlaceHolder();
Context context = FeedSurferApp.getContext();
FeedSurferApp
.getPicasso()
.load(source)
.error(ResourcesCompat.getDrawable(context.getResources(), R.drawable.connection_error, context.getTheme()))
.into(drawable);
return drawable;
}
private class BitmapDrawablePlaceHolder extends BitmapDrawable implements Target {
protected Drawable drawable;
#Override
public void draw(final Canvas canvas) {
if (drawable != null) {
drawable.draw(canvas);
}
}
public void setDrawable(Drawable drawable) {
this.drawable = drawable;
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
if (textView != null) {
textView.setText(textView.getText());
}
}
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
setDrawable(new BitmapDrawable(FeedSurferApp.getContext().getResources(), bitmap));
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
setDrawable(errorDrawable);
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {}
}
}
I found a way to use ImageGetter with Picasso Target:
public Drawable getDrawable(String source) {
final BitmapDrawablePlaceHolder result = new BitmapDrawablePlaceHolder();
Picasso.with(getContext()).load(source).into(new Target() {
#Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
final BitmapDrawable drawable = new BitmapDrawable(mContext.getResources(), bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
result.setDrawable(drawable);
result.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
content.setText(content.getText());
// cache is now warmed up
}
#Override public void onBitmapFailed(Drawable errorDrawable) { }
#Override public void onPrepareLoad(Drawable placeHolderDrawable) { }
});
return result;
}
This uses the cache and is no longer a synchronous call requiring the AsyncTask.
Credit to: Fetch images with Callback in Picasso?
Another simple way to use Picasso is to create a custom TextView and make it implement Target interface of Picasso.
Then you can do something as simple as this.
Picasso.get().load("Some_img_url").placeholder(R.drawable.ic_launcher_foreground).into(tv)
Below is the class
class TextViewWithImageLoader #JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : AppCompatTextView(context, attrs, defStyleAttr), Target {
enum class Direction { START, END, TOP, BOTTOM }
private var mWidthInPixels: Int = 0
private var mHeightInPixels: Int = 0
private var mDirection: Direction = Direction.START //default value
// This method initialize the required parameters for the TextView to load the image
fun setupImageLoader(widthInPixels: Int, heightInPixels: Int, direction: Direction) {
mWidthInPixels = widthInPixels
mHeightInPixels = heightInPixels
mDirection = direction
}
// sets the size of the drawable
private fun setDrawableBounds(drawable: Drawable) {
drawable.setBounds(0, 0, mWidthInPixels, mHeightInPixels)
}
// Sets the initial placeholder drawable
override fun onPrepareLoad(placeHolderDrawable: Drawable?) {
//checking if height and width are valid
if (placeHolderDrawable != null && mWidthInPixels > 0 && mHeightInPixels > 0) {
setDrawableBounds(placeHolderDrawable)
setDrawable(placeHolderDrawable)
}
}
// set the drawable based on the Direction enum
private fun setDrawable(placeHolderDrawable: Drawable?) {
when (mDirection) {
Direction.START -> setCompoundDrawables(placeHolderDrawable, null, null, null);
Direction.END -> setCompoundDrawables(null, null, placeHolderDrawable, null);
Direction.TOP -> setCompoundDrawables(null, placeHolderDrawable, null, null);
Direction.BOTTOM -> setCompoundDrawables(null, null, null, placeHolderDrawable);
}
}
//In this method we receive the image from the url
override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) {
//checking if height and width are valid
if (mWidthInPixels > 0 && mHeightInPixels > 0) {
val drawable = BitmapDrawable(resources, bitmap)
setDrawableBounds(drawable)
setDrawable(drawable)
}
}
override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {
//Do nothing as we are already setting a default value in onPrepareLoad method
// you can add your logic here if required
}
}
You can use this class directly or if you currently have your own custom view then just extend this class.
You can either go through this medium article for more details
OR
You can see the sample project on github

Categories

Resources