Get the ID of a drawable in ImageView

142,708

Solution 1

I think if I understand correctly this is what you are doing.

ImageView view = (ImageView) findViewById(R.id.someImage);
view.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        ImageView imageView = (ImageView) view;
        assert(R.id.someImage == imageView.getId());

        switch(getDrawableId(imageView)) {
            case R.drawable.foo:
                imageView.setDrawableResource(R.drawable.bar);
                break;
            case R.drawable.bar:
            default:
                imageView.setDrawableResource(R.drawable.foo);
            break;
        }
    });

Right? So that function getDrawableId() doesn't exist. You can't get a the id that a drawable was instantiated from because the id is just a reference to the location of data on the device on how to construct a drawable. Once the drawable is constructed it doesn't have a way to get back the resourceId that was used to create it. But you could make it work something like this using tags

ImageView view = (ImageView) findViewById(R.id.someImage);
view.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        ImageView imageView = (ImageView) view;
        assert(R.id.someImage == imageView.getId());

        // See here
        Integer integer = (Integer) imageView.getTag();
        integer = integer == null ? 0 : integer;

        switch(integer) {
        case R.drawable.foo:
            imageView.setDrawableResource(R.drawable.bar);
            imageView.setTag(R.drawable.bar);
            break;
        case R.drawable.bar:
        default:
            imageView.setDrawableResource(R.drawable.foo);
            imageView.setTag(R.drawable.foo);
            break;
        }
    });

Solution 2

I answered something like this in another question already, but will change it just a little for this one.

Unfortunately, there is no getImageResource() or getDrawableId(). But, I created a simple workaround by using the ImageView tags.

In onCreate():

imageView0 = (ImageView) findViewById(R.id.imageView0);
imageView1 = (ImageView) findViewById(R.id.imageView1);
imageView2 = (ImageView) findViewById(R.id.imageView2);

imageView0.setTag(R.drawable.apple);
imageView1.setTag(R.drawable.banana);
imageView2.setTag(R.drawable.cereal);

Then, if you like, you can create a simple function to get the drawable id:

private int getDrawableId(ImageView iv) {
    return (Integer) iv.getTag();
}

Too easy.

Solution 3

As of today, there is no support on this function. However, I found a little hack on this one.

 imageView.setImageResource(R.drawable.ic_star_black_48dp);
 imageView.setTag(R.drawable.ic_star_black_48dp);

So if you want to get the ID of the view, just get it's tag.

if (imageView.getTag() != null) {
   int resourceID = (int) imageView.getTag();

   //
   // drawable id.
   //   
}

Solution 4

A simple solution might be to just store the drawable id in a temporary variable. I'm not sure how practical this would be for your situation but it's definitely a quick fix.

Solution 5

Digging StackOverflow for answers on the similar issue I found people usually suggesting 2 approaches:

  • Load a drawable into memory and compare ConstantState or bitmap itself to other one.
  • Set a tag with drawable id into a view and compare tags when you need that.

Personally, I like the second approach for performance reason but tagging bunch of views with appropriate tags is painful and time consuming. This could be very frustrating in a big project. In my case I need to write a lot of Espresso tests which require comparing TextView drawables, ImageView resources, View background and foreground. A lot of work.

So I eventually came up with a solution to delegate a 'dirty' work to the custom inflater. In every inflated view I search for a specific attributes and and set a tag to the view with a resource id if any is found. This approach is pretty much the same guys from Calligraphy used. I wrote a simple library for that: TagView

If you use it, you can retrieve any of predefined tags, containing drawable resource id that was set in xml layout file:

TagViewUtils.getTag(view, ViewTag.IMAGEVIEW_SRC.id)
TagViewUtils.getTag(view, ViewTag.TEXTVIEW_DRAWABLE_LEFT.id)
TagViewUtils.getTag(view, ViewTag.TEXTVIEW_DRAWABLE_TOP.id)
TagViewUtils.getTag(view, ViewTag.TEXTVIEW_DRAWABLE_RIGHT.id)
TagViewUtils.getTag(view, ViewTag.TEXTVIEW_DRAWABLE_BOTTOM.id)
TagViewUtils.getTag(view, ViewTag.VIEW_BACKGROUND.id)
TagViewUtils.getTag(view, ViewTag.VIEW_FOREGROUND.id)

The library supports any attribute, actually. You can add them manually, just look into the Custom attributes section on Github. If you set a drawable in runtime you can use convenient library methods:

setImageViewResource(ImageView view, int id)

In this case tagging is done for you internally. If you use Kotlin you can write a handy extensions to call view itself. Something like this:

fun ImageView.setImageResourceWithTag(@DrawableRes int id) {
    TagViewUtils.setImageViewResource(this, id)
}

You can find additional info in Tagging in runtime

Share:
142,708
chikka.anddev
Author by

chikka.anddev

Updated on March 22, 2020

Comments

  • chikka.anddev
    chikka.anddev about 4 years

    I have one ImageView and set a drawable on it. Now I need to get the ID of the drawable on click event of ImageView dynamically. How can I get it?

    imgtopcolor = (ImageView) findViewById(R.id.topcolor); 
    imgtopcolor.setImageResource(R.drawable.dr);  // How do I get this back?
    

    Now on touch event of imgtopcolor i want to need drawable id because I am setting different drawable each time and want to compare the drawable with other

  • chikka.anddev
    chikka.anddev over 13 years
    Thanks for reply.but i think there is no such method like getDrawableID().
  • chikka.anddev
    chikka.anddev over 13 years
    ya sure but i have to than convert the tag object into integer to get tag.and my job is done
  • Greg Giacovelli
    Greg Giacovelli over 13 years
    cool srry I didn't have a compiler for that one. Just make sure to try to use Integer.valueOf() instead of doing new Integer(). It just creates more waste if you use new for integers that should be recycled. Hopefully less than 256.
  • Cote Mounyo
    Cote Mounyo over 10 years
    What do I set in tag in xml file? do I do android:tag="@drawable/foo"
  • Greg Giacovelli
    Greg Giacovelli over 10 years
    If you are statically defining it in xml, at that point you might as well just use the imageView id. As far as I know setting a tag in xml only sets the tag to a string.
  • Ruchir Baronia
    Ruchir Baronia over 8 years
    Can you set the tags to regular drawable image objects?
  • Anonsage
    Anonsage over 8 years
    The tag can be set to any Object.
  • Kikiwa
    Kikiwa about 8 years
    Bad idea, the view ids are used for other things and you shuold not do that, never. Ex: you set a random id to a view and then you want to access the view ... how can you identify it since you've lost the previous layout id? :/
  • ADM
    ADM over 7 years
    You can set the Draawable Id as tag on view if you wanna save it for later
  • Ultimo_m
    Ultimo_m almost 6 years
    or using content description could be a possible solution if you dont use it for testing purposes
  • Greg Giacovelli
    Greg Giacovelli almost 6 years
    @Ultimo_m I would only advise against that because that is not only for testing purposes but for accessibility. A screen reader would use this to describe the image to a visually impaired user of your app. You should always fill that field out with meaningful content describing the representation of the image.
  • Ultimo_m
    Ultimo_m almost 6 years
    You're right :). That's something developers should pay attention to