web-dev-qa-db-fra.com

Obtenir l'ID d'un dessinable dans ImageView

J'ai un ImageView et un dessin sur celui-ci. Maintenant, j'ai besoin d'obtenir l'ID de l'événement extractible sur clic de ImageView de manière dynamique. Comment puis-je l'avoir?

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

Maintenant, dans l’événement tactile de imgtopcolor, je veux avoir besoin d’un identifiant extractible, car j’utilise différents dessinables à chaque fois et je veux comparer ce dessinable avec d’autres.

48
chikka.anddev

Je pense que si je comprends bien, c'est ce que vous faites.

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

Droite? Donc, cette fonction getDrawableId() n'existe pas. Vous ne pouvez pas obtenir un identifiant à partir duquel un dessinable a été instancié, car cet identifiant est simplement une référence à l'emplacement des données sur le périphérique pour savoir comment construire un dessinable. Une fois que le dessinable est construit, il n'a plus aucun moyen de récupérer l'identifiant de ressource utilisé pour le créer. Mais vous pourriez le faire fonctionner comme ceci en utilisant 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

J'ai déjà répondu à quelque chose comme ceci dans une autre question, mais je vais le changer un peu pour celui-ci.

Malheureusement, il n'y a pas getImageResource() ou getDrawableId(). Mais, j'ai créé une solution de contournement simple en utilisant les balises ImageView.

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

Ensuite, si vous le souhaitez, vous pouvez créer une fonction simple pour obtenir l'identifiant extractible:

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

Trop facile.

30
Anonsage

A ce jour, il n'y a pas de support pour cette fonction. Cependant, j'ai trouvé un petit bidouillage sur celui-ci.

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

Donc, si vous voulez obtenir l'ID de la vue, il suffit d'obtenir son tag.

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

   //
   // drawable id.
   //   
}
6
ralphgabb

Une solution simple pourrait consister simplement à stocker l'identifiant extractible dans une variable temporaire. Je ne sais pas si cela serait pratique dans votre cas, mais c'est définitivement une solution rapide.

1
justinl

Creuser StackOverflow pour obtenir des réponses sur un problème similaire, j’ai trouvé des personnes suggérant généralement deux approches:

  • Chargez un dessin en mémoire et comparez ConstantState ou bitmap lui-même à un autre.
  • Définissez une balise avec un identifiant pouvant être dessiné dans une vue et comparez-les lorsque vous en avez besoin.

Personnellement, j'aime bien la deuxième approche pour des raisons de performances, mais étiqueter des vues avec des balises appropriées est pénible et prend du temps. Cela pourrait être très frustrant dans un grand projet. Dans mon cas, j'ai besoin d'écrire beaucoup de tests d'espresso qui nécessitent de comparer TextView dessinables, ImageView ressources, View de fond et d'avant-plan. Beaucoup de travail.

J'ai donc finalement trouvé une solution pour déléguer un travail "sale" à l'inflater personnalisé. Dans chaque vue gonflée, je recherche un attribut spécifique et associe une balise à la vue avec un identifiant de ressource, le cas échéant. Cette approche est à peu près les mêmes gars de Calligraphie utilisé. J'ai écrit une bibliothèque simple pour cela: TagView

Si vous l'utilisez, vous pouvez récupérer n'importe quelle balise prédéfinie, contenant l'ID de ressource pouvant être dessiné défini dans le fichier de présentation XML:

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)

La bibliothèque supporte n'importe quel attribut, en fait. Vous pouvez les ajouter manuellement, il suffit de regarder dans la section Attributs personnalisés sur Github. Si vous définissez un dessin au runtime, vous pouvez utiliser des méthodes de bibliothèque pratiques:

setImageViewResource(ImageView view, int id)

Dans ce cas, le marquage est fait pour vous en interne. Si vous utilisez Kotlin, vous pouvez écrire une extension pratique pour appeler la vue elle-même. Quelque chose comme ça:

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

Vous pouvez trouver des informations supplémentaires dans marquage dans le runtime

1
Bogdan Kornev

Encore plus facilement: il suffit de stocker l'identifiant R.drawable Dans l'identifiant de la vue: utilisez v.setId(). Puis récupérez-le avec v.getId().

0
Peri Hartman

J'ai récemment rencontré le même problème. Je l'ai résolu par implémentant mon propre ImageView classe.

Voici mon implémentation de 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