9

I need entry chips to be added dynamically using material design library along with icon which will be retrieved through API call. How to use Glide library to set chip icon?

NOTE : I am not saving any images before in drawable folder. All the data is being retrieved through API call.

Eswar
  • 199
  • 1
  • 13
  • https://bumptech.github.io/glide/doc/getting-started.html. Non View Targets. Just call setChipIcon with the drawable resource. – Raghunandan Aug 19 '19 at 10:34
  • @Raghunandan - I am familiar in using Glide. But in my case - i don't have any specific UI elements like ImageView. I want it to be in chipIcon. As we know - setChipIcon() accepts only images which we have saved before in folder. – Eswar Aug 19 '19 at 10:42
  • No you can set a drawable that drawable downloaded from a url.https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/chip/Chip.java line 1456 and you have `public void onResourceReady(Drawable resource, Transition transition) {` drawable from glide – Raghunandan Aug 19 '19 at 10:44
  • but, will those images saved in drawable removed after using? i don't need anything to be saved. If you don't mind - can you explain with codeSnippet. – Eswar Aug 19 '19 at 10:47
  • just follow the glide docs in non view targets. if you don't want to cache https://bumptech.github.io/glide/doc/caching.html check skip caching section – Raghunandan Aug 19 '19 at 10:48

3 Answers3

10

You can use this workaround for example. Customize Chip:

public class GlideChip extends Chip {

    public GlideChip(Context context) {
        super(context);
    }

    public GlideChip(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * Set an image from an URL for the {@link Chip} using {@link com.bumptech.glide.Glide}
     * @param url icon URL
     * @param errDrawable error icon if Glide return failed response
     */
    public GlideChip setIconUrl(String url, Drawable errDrawable) {
        Glide.with(this)
                .load(url)
                .listener(new RequestListener<Drawable>() {
                    @Override
                    public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                        setChipIcon(errDrawable);
                        return false;
                    }

                    @Override
                    public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                        setChipIcon(resource);
                        return false;
                    }
                }).preload();
        return this;
    }

}

Create GlideChip, add to the chip group and start the project:

public class ChipFragment extends Fragment {

    private ChipGroup chipGroup;

    public ChipFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_chip, container, false);
        chipGroup = view.findViewById(R.id.chipGroup);
        Chip chip = createChip("John Doe", "https://i1.sndcdn.com/avatars-000197335271-mztyvq-t500x500.jpg");
        chipGroup.addView(chip);
        return view;
    }

    private Chip createChip(String name, String avatarUrl) {
        GlideChip chip = new GlideChip(getContext());
        chip.setText(name);
        chip.setIconUrl(avatarUrl, getResources().getDrawable(R.drawable.err_avatar));
        chip.setClickable(true);
        chip.setFocusable(true);
        return chip;
    }

}

P/S... Don't forget to add Glide to build.gradle. See here

Javis
  • 283
  • 4
  • 7
3

For Coil and Kotlin lovers, I made a CoilChip based on @Javis's answer. (Kudos to Javis!)

class CoilChip(context: Context?) : Chip(context) {
    /**
     * @param url icon URL
     * @param errDrawable set error icon in onError callback
     */
    fun setIconUrl(url: String, placeholderDrawable: Drawable?, errDrawable: Drawable?) {
        chipDrawable?.let {
            val request = ImageRequest.Builder(context)
                .data(url)
                .target(
                    onStart = { placeholder ->
                        chipIcon = placeholderDrawable
                    },
                    onSuccess = { result ->
                        chipIcon = result
                    },
                    onError = { error ->
                        chipIcon = errDrawable
                    })
//              .memoryCachePolicy(CachePolicy.DISABLED) // caching strategy             
                .build()

            val imageLoader = ImageLoader.Builder(context)
                .build()
            imageLoader.enqueue(request)
        }
    }
}

If you encounter the exception Software rendering doesn't support hardware bitmaps, add the following to your image request.

.bitmapConfig(Bitmap.Config.ARGB_8888)

Cheers!

clement.l
  • 189
  • 1
  • 6
  • unable to resolve `ImageLoader` and `ImageRequest` . Can provide what to import for those.. – Shadman Akhtar Dec 05 '22 at 09:04
  • @ShadmanAkhtar Hi! I'm using the latest version of Coil, namely `2.2.2`. fyi, the imports are`import coil.ImageLoader` and`import coil.request.ImageRequest` – clement.l Dec 07 '22 at 02:46
1

The provided answer will occasionally lead to a crash:

java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.isRecycled()' on a null object reference
at android.graphics.Canvas.throwIfCannotDraw(Canvas.java:1270)
at android.view.DisplayListCanvas.throwIfCannotDraw(DisplayListCanvas.java:257)
at android.graphics.Canvas.drawBitmap(Canvas.java:1415)
at com.bumptech.glide.load.resource.gif.GifDrawable.draw(SourceFile:291)
at com.google.android.material.chip.ChipDrawable.drawChipIcon(SourceFile:652)
at com.google.android.material.chip.ChipDrawable.draw(SourceFile:568)
at android.graphics.drawable.DrawableWrapper.draw(DrawableWrapper.java:228)
...

This is because drawable isn't cleared correctly. The correct implementation would be (the example is in Kotlin):

    Glide.with(this)
                .load(url)
                .into(object : CustomTarget<Drawable>(200, 200) { //size might be omitted

            override fun onLoadFailed(errorDrawable: Drawable?) {
                chipIcon = errDrawable
            }

            override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
                chipIcon = resource
            }

            override fun onLoadCleared(placeholder: Drawable?) {
                chipIcon = placeholder
            }

        })
Deinlandel
  • 1,023
  • 8
  • 25