Réponses:
Disons que vous générez un tas de vues similaires. Vous pouvez définir un OnClickListener
pour chaque vue individuellement:
button1.setOnClickListener(new OnClickListener ... );
button2.setOnClickListener(new OnClickListener ... );
...
Ensuite, vous devez créer une onClick
méthode unique pour chaque vue, même si elles font les mêmes choses, comme:
public void onClick(View v) {
doAction(1); // 1 for button1, 2 for button2, etc.
}
En effet, il onClick
n'a qu'un seul paramètre, a View
, et il doit obtenir d'autres informations à partir des variables d'instance ou des variables locales finales dans les étendues englobantes. Ce que nous voulons vraiment, c'est obtenir des informations à partir des vues elles-mêmes .
Entrez getTag
/ setTag
:
button1.setTag(1);
button2.setTag(2);
Maintenant, nous pouvons utiliser le même OnClickListener pour chaque bouton:
listener = new OnClickListener() {
@Override
public void onClick(View v) {
doAction(v.getTag());
}
};
C'est essentiellement un moyen pour les vues d'avoir des souvenirs .
public void ui_click(View view){ if(20==((int)view.getTag())) view.setBackgroundColor(colorInt); }
devrait faire l'affaire pour la partie couleur. 20 n'est qu'un espace réservé pour la position de validation de votre vue.
Je voudrais ajouter quelques mots.
Bien que l'utilisation get/setTag(Object)
semble être très utile dans le cas particulier d'un modèle ViewHolder, je recommande de réfléchir à deux fois avant de l'utiliser dans d'autres cas. Il existe presque toujours une autre solution avec un meilleur design.
La raison principale est qu'un code comme celui-ci devient assez rapidement insupportable.
Il n'est pas évident pour les autres développeurs ce que vous avez conçu pour stocker comme balise dans la vue. Les méthodes setTag/getTag
ne sont pas du tout descriptives.
Il stocke juste un Object
, qui doit être lancé lorsque vous le souhaitez getTag
. Vous pouvez obtenir des plantages inattendus plus tard lorsque vous décidez de modifier le type d'objet stocké dans la balise.
Voici une histoire réelle: nous avions un assez gros projet avec beaucoup d'adaptateurs, des opérations asynchrones avec des vues, etc. Un développeur a décidé de le faire set/getTag
dans sa partie du code, mais un autre a déjà défini la balise sur cette vue. En fin de compte, quelqu'un n'a pas pu trouver sa propre étiquette et était très confus. Il nous a fallu plusieurs heures pour trouver le bug.
setTag(int key, Object tag)
semble beaucoup mieux, car vous pouvez générer des clés uniques pour chaque balise (en utilisant les ressources id ), mais il existe une restriction importante pour Android <4.0. De documents Lint:
Avant Android 4.0, l'implémentation de View.setTag (int, Object) stockait les objets dans une carte statique, où les valeurs étaient fortement référencées. Cela signifie que si l'objet contient des références pointant vers le contexte, le contexte (qui pointe à peu près tout le reste) fuira. Si vous passez une vue, la vue fournit une référence au contexte qui l'a créée. De même, les détenteurs de vues contiennent généralement une vue et les curseurs sont parfois également associés à des vues.
Nous pouvons utiliser setTag()
et getTag()
pour définir et obtenir des objets personnalisés selon nos besoins. La setTag()
méthode prend un argument de type Object
et getTag()
retourne un Object
.
Par exemple,
Person p = new Person();
p.setName("Ramkailash");
p.setId(2000001);
button1.setTag(p);
Ceci est très utile pour une ArrayAdapter
utilisation personnalisée . C'est une sorte d'optimisation. Il setTag
utilisé comme référence à l'objet qui fait référence à certaines parties de la mise en page (celle qui s'affiche dans ListView
) au lieu de findViewById
.
static class ViewHolder {
TextView tvPost;
TextView tvDate;
ImageView thumb;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = myContext.getLayoutInflater();
convertView = inflater.inflate(R.layout.postitem, null);
ViewHolder vh = new ViewHolder();
vh.tvPost = (TextView)convertView.findViewById(R.id.postTitleLabel);
vh.tvDate = (TextView)convertView.findViewById(R.id.postDateLabel);
vh.thumb = (ImageView)convertView.findViewById(R.id.postThumb);
convertView.setTag(vh);
}
....................
}
Contrairement aux ID, les balises ne sont pas utilisées pour identifier les vues. Les balises sont essentiellement des informations supplémentaires qui peuvent être associées à une vue. Ils sont le plus souvent utilisés pour faciliter le stockage des données relatives aux vues dans les vues elles-mêmes plutôt que pour les placer dans une structure distincte.
Référence: http://developer.android.com/reference/android/view/View.html
La définition de TAG est vraiment utile lorsque vous disposez d'un ListView et que vous souhaitez recycler / réutiliser les vues. De cette façon, le ListView devient très similaire au nouveau RecyclerView.
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
if ( convertView == null )
{
/* There is no view at this position, we create a new one.
In this case by inflating an xml layout */
convertView = mInflater.inflate(R.layout.listview_item, null);
holder = new ViewHolder();
holder.toggleOk = (ToggleButton) convertView.findViewById( R.id.togOk );
convertView.setTag (holder);
}
else
{
/* We recycle a View that already exists */
holder = (ViewHolder) convertView.getTag ();
}
// Once we have a reference to the View we are returning, we set its values.
// Here is where you should set the ToggleButton value for this item!!!
holder.toggleOk.setChecked( mToggles.get( position ) );
return convertView;
}