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.
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;
}
});
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.
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.
//
}
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.
Creuser StackOverflow pour obtenir des réponses sur un problème similaire, j’ai trouvé des personnes suggérant généralement deux approches:
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
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()
.
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
}
}