60

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

OneCricketeer
  • 126,858
  • 14
  • 92
  • 185
chikka.anddev
  • 9,196
  • 7
  • 35
  • 45

7 Answers7

64

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;
        }
    });
OneCricketeer
  • 126,858
  • 14
  • 92
  • 185
Greg Giacovelli
  • 9,896
  • 2
  • 43
  • 60
  • Thanks for reply.but i think there is no such method like getDrawableID(). – chikka.anddev Dec 25 '10 at 05:21
  • ya sure but i have to than convert the tag object into integer to get tag.and my job is done – chikka.anddev Jan 01 '11 at 05:12
  • 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. – Greg Giacovelli Jan 03 '11 at 00:46
  • What do I set in tag in xml file? do I do `android:tag="@drawable/foo"` – Cote Mounyo Aug 23 '13 at 20:13
  • 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. – Greg Giacovelli Aug 26 '13 at 19:45
  • or using content description could be a possible solution if you dont use it for testing purposes – Ultimo_m Jun 18 '18 at 12:57
  • @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. – Greg Giacovelli Jul 11 '18 at 15:29
  • You're right :). That's something developers should pay attention to – Ultimo_m Jul 11 '18 at 15:38
35

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.

Anonsage
  • 7,194
  • 3
  • 41
  • 50
7

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.
   //   
}
ralphgabb
  • 9,100
  • 2
  • 41
  • 48
1

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.

justinl
  • 9,764
  • 19
  • 67
  • 87
1

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

Bogdan Kornev
  • 71
  • 1
  • 4
1

I recently run into the same problem. I solved it by implementing my own ImageView class.

Here is my Kotlin implementation:

class MyImageView(context: Context): ImageView(context) {
    private var currentDrawableId: Int? = null

    override fun setImageResource(resId: Int) {
        super.setImageResource(resId)
        currentDrawableId = resId
    }

    fun getDrawableId() {
        return currentDrawableId
    }

    fun compareCurrentDrawable(toDrawableId: Int?): Boolean {
        if (toDrawableId == null || currentDrawableId != toDrawableId) {
            return false
        }

        return true
    }

}
kraspa11
  • 11
  • 1
0

Even easier: just store the R.drawable id in the view's id: use v.setId(). Then get it back with v.getId().

OneCricketeer
  • 126,858
  • 14
  • 92
  • 185
Peri Hartman
  • 17,906
  • 17
  • 49
  • 85
  • 2
    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? :/ – Kikiwa Apr 25 '16 at 16:17
  • You can set the Draawable Id as tag on view if you wanna save it for later – ADM Aug 10 '16 at 19:44