在ImageView中获取可绘制对象的ID

73

我有一个ImageView,并在其上设置了一个drawable。现在我需要动态地在 ImageView 的点击事件中获取该drawable的ID。我应该如何获取它?

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

现在,在imgtopcolor的触摸事件中,我想要获取可绘制资源的ID,因为我每次都设置不同的可绘制资源,并且想要将其与其他资源进行比较。


请粘贴您的代码。 - Cristian
7个回答

68

我认为如果我理解正确,这就是你正在做的事情。

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;
        }
    });

是的,所以函数getDrawableId()不存在。你无法获取从哪个id实例化的drawable,因为id只是一个引用,指向设备上构建drawable所需的数据位置。一旦drawable被构建,它就无法返回用于创建它的resourceId。但是你可以使用标签这样使其工作。

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;
        }
    });

1
谢谢回复。但我认为没有像getDrawableID()这样的方法。 - chikka.anddev
好的,但我必须先将标签对象转换为整数才能获取标签。然后我的工作就完成了。 - chikka.anddev
很酷,抱歉我没有为那个编译器。只需确保尝试使用Integer.valueOf()而不是使用new Integer()。如果您对应该回收的整数使用new,则会产生更多浪费。希望小于256。 - Greg Giacovelli
我应该在XML文件的标签中设置什么?我需要这样做吗:android:tag="@drawable/foo" - Cote Mounyo
如果您在xml中静态定义它,那么最好直接使用imageView id。据我所知,在xml中设置标签只会将标签设置为字符串。 - Greg Giacovelli
显示剩余3条评论

37

我之前在另一个问题中已经回答了类似的内容,但是针对这个问题稍微做出了一些改变。

不幸的是,没有 getImageResource() 或者 getDrawableId() 函数。但是,我通过使用 ImageView 标签创建了一个简单的解决方法。

在 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);

然后,如果您愿意,可以创建一个简单的函数来获取可绘制资源的ID:

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

太容易了。


1
你能将标签设置为常规的可绘制图像对象吗? - Ruchir Baronia
1
标签可以设置为任何“对象”。 - Anonsage

10

截至今日,此功能暂无支持。但是,我找到了一个小技巧。

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

所以,如果你想获取视图的ID,只需获取它的标签。

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

   //
   // drawable id.
   //   
}

2
在查找类似问题的答案时,我在StackOverflow上发现人们通常建议两种方法:
  • 将可绘制对象加载到内存中,并将ConstantState或位图本身与其他对象进行比较。
  • 将具有可绘制对象ID的标签设置到视图中,并在需要时比较标签。
就个人而言,出于性能原因,我更喜欢第二种方法,但是使用适当的标签标记大量视图很繁琐且耗时。在大型项目中,这可能非常令人沮丧。在我的情况下,我需要编写许多Espresso测试,这些测试需要比较TextView可绘制对象、ImageView资源、View背景和前景。这是一项艰巨的工作。
所以,我最终想出了一种解决方案,将“脏”工作委托给自定义的布局填充器。在每个充气的视图中,我搜索特定的属性,并在找到任何资源ID时向视图设置标签。这种方法与Calligraphy团队使用的方法非常相似。我为此编写了一个简单的库:TagView
如果您使用它,可以检索包含在XML布局文件中设置的可维护标签之一,其中包含可绘制资源ID。
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)

该库实际上支持任何属性。您可以手动添加它们,只需查看Github上的自定义属性部分即可。如果您在运行时设置了可绘制对象,则可以使用方便的库方法:
setImageViewResource(ImageView view, int id)

在这种情况下,标记是在内部为您完成的。如果您使用 Kotlin,您可以编写一个便捷的扩展来调用视图本身。类似于这样的东西:
fun ImageView.setImageResourceWithTag(@DrawableRes int id) {
    TagViewUtils.setImageViewResource(this, id)
}

您可以在运行时标记中找到更多信息。

2
我最近遇到了同样的问题,我通过实现自己的ImageView类来解决它。
这是我的Kotlin实现:
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
    }

}

1
一个简单的解决方案可能是只需将可绘制的ID存储在临时变量中。我不确定这对你的情况有多实用,但肯定是一个快速修复。

-1
更简单的方法是:只需将R.drawable id存储在视图的id中,使用v.setId()即可。然后使用v.getId()获取它。

2
不好的想法,视图ID用于其他事情,你不应该这样做,永远不要这样做。例如:您将随机ID设置为视图,然后希望访问该视图...由于您已丢失先前的布局ID,因此如何识别它? :/ - Kikiwa
如果您想要将Drawable Id保存以备后用,可以将其设置为视图的标签。 - ADM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接