web-dev-qa-db-ja.com

ImageViewでドロアブルのIDを取得します

ImageViewが1つあり、その上にドロアブルを設定します。ここで、ImageViewのクリックイベントで動的にドロアブルのIDを取得する必要があります。どうすれば入手できますか?

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

imgtopcolorのタッチイベントで、毎回異なるdrawableを設定し、他のドローアブルと比較したいので、ドローアブルIDが必要です。

48
chikka.anddev

私が正しく理解していれば、これがあなたがしていることだと思います。

_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は、ドロウアブルの構築方法に関するデバイス上のデータの場所への単なる参照であるため、ドロウアブルがインスタンス化されたIDを取得することはできません。一度ドロアブルが構築されると、それを作成するために使用されたresourceIdを取得する方法がありません。しかし、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;
        }
    });
_
52
Greg Giacovelli

私はすでに別の質問でこのようなことを回答しましたが、これについては少し変更します。

残念ながら、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();
}

簡単すぎる。

30
Anonsage

現在、この機能はサポートされていません。しかし、私はこれについて少しハックを見つけました。

 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.
   //   
}
6
ralphgabb

単純な解決策は、一時変数にドローアブルIDを保存することです。これがあなたの状況にとってどれほど実用的かは分かりませんが、間違いなく簡単な修正です。

1
justinl

StackOverflowを掘って同様の問題の答えを見つけました。私は通常、2つのアプローチを提案している人々を見つけました。

  • ドロアブルをメモリにロードし、 ConstantState またはビットマップ自体を他のものと比較します。
  • 描画可能なIDを持つタグをビューに設定し、必要なときにタグを比較します。

個人的には、パフォーマンス上の理由から2番目のアプローチが好きですが、適切なタグで多数のビューをタグ付けするのは苦痛で時間がかかります。これは、大きなプロジェクトでは非常にイライラする可能性があります。私の場合、TextViewドロアブル、ImageViewリソース、Viewバックグラウンドとフォアグラウンドの比較を必要とする多くのEspressoテストを書く必要があります。多くの作業。

だから私は最終的に、カスタムインフレータに「汚い」作業を委任するソリューションを思い付きました。膨張したすべてのビューで、特定の属性を検索し、リソースIDが見つかった場合はビューにタグを設定します。このアプローチは、 書道 の使用者とほとんど同じです。そのためのシンプルなライブラリを作成しました: 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)
}

追加情報は 実行時のタグ付け にあります。

1
Bogdan Kornev

さらに簡単:_R.drawable_ idをビューのidに保存するだけで、v.setId()を使用します。次に、v.getId()で取得します。

0
Peri Hartman

私は最近同じ問題に遭遇しました。 独自の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
    }

}
0
kraspa11