web-dev-qa-db-fra.com

Comment attribuer un ID à une vue par programme?

Dans un fichier XML, nous pouvons affecter un ID à une vue telle que Android:id="@+id/something", puis appeler findViewById(), mais lors de la création d'une vue par programme, comment puis-je affecter un ID?

Je pense que setId() n'est pas la même chose que l'affectation par défaut. setId() est extra.

Quelqu'un peut-il me corriger?

193
DuyguK

Android id overview

Un Android id est un entier couramment utilisé pour identifier les vues. id peut être assigné via XML (si possible) et via code (par programmation). Le id est très utile pour obtenir des références pour le nom défini par XML Views généré par un Inflater (comme en utilisant setContentView.)

Attribuer id via XML

  • Ajoutez un attribut de Android:id="@+id/somename" à votre vue.
  • Lorsque votre application est créée, le Android:id se voit attribuer un niqueint à utiliser dans le code.
  • Référencez la valeur int de Android:id dans le code en utilisant "R.id.somename" (en fait, une constante.)
  • this int peut changer de build en build donc ne jamais copier un identifiant de gen/package.name/R.Java _, utilisez simplement "R.id.somename".
  • (En outre, un id attribué à un Preference dans XML n'est pas utilisé lorsque Preference génère son View.)

Attribuer id via code (par programme)

  • Définissez manuellement ids à l'aide de someView.setId(int);
  • int doit être positif, mais est sinon arbitraire - il peut être ce que vous voulez (continuez à lire si cela est effrayant).
  • Par exemple, si vous créez et numérotez plusieurs vues représentant des éléments, vous pouvez utiliser leur numéro d'élément.

Unicité de ids

  • XML- assigné ids sera unique.
  • ids assigné par code ne pas doit être unique
  • ids assigné par code peut (théoriquement) entrer en conflit avec XML- assigné ids.
  • Ces noms ids conflictuels n’auront pas d’importance s’ils sont interrogés correctement (continuer à lire) .

Quand (et pourquoi) les conflits ids ne comptent pas

  • findViewById(int) va parcourir récursivement la profondeur d'abord dans la hiérarchie de la vue spécifiée et renvoie le premier View qu'il trouve avec un id correspondant.
  • Tant qu'il n'y a pas ids assigné par code avant un id défini par XML dans la hiérarchie, findViewById(R.id.somename) retournera toujours la vue définie par XML afin que id 'd.

Création dynamique de vues et affectation de IDs

  • Dans XML de présentation, définissez un ViewGroup vide avec id.
  • Tels qu'un LinearLayout avec Android:id="@+id/placeholder".
  • Utilisez le code pour remplir l'espace réservé ViewGroup avec Views.
  • Si vous avez besoin ou si vous le souhaitez, affectez les ids qui conviennent à chaque vue.
  • Interrogez ces vues enfant à l'aide de placeholder.findViewById (convenientInt);

  • L'API 17 a introduit View.generateViewId() qui permet de générer un identifiant unique.

Si vous choisissez de conserver des références à vos vues, veillez à les instancier avec getApplicationContext() et à définir chaque référence sur null dans onDestroy. Apparemment fuir le Activity (s'accrocher après qu'il soit détruit) est inutile .. :)

Réserver un XML Android:id à utiliser dans le code

API 17 introduite View.generateViewId() qui génère un identifiant unique. (Merci à take-chances-make-changes pour l'avoir signalé.) *

Si votre ViewGroup ne peut pas être défini via XML (ou si vous ne le souhaitez pas), vous pouvez réserver l'ID via XML pour vous assurer qu'il reste unique:

Ici, valeurs/ids.xml définit un nom personnalisé id:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="reservedNamedId" type="id"/>
</resources>

Ensuite, une fois que le ViewGroup ou View a été créé, vous pouvez attacher l'id personnalisé

myViewGroup.setId(R.id.reservedNamedId);

Exemple id en conflit

Pour plus de clarté au moyen d'un exemple obscurcissant, examinons ce qui se passe lorsqu'il existe un conflit id dans les coulisses.

layout/mylayout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical" >
    <LinearLayout
        Android:id="@+id/placeholder"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:orientation="horizontal" >
</LinearLayout>

Pour simuler un conflit, disons que notre dernière construction affectée R.id.placeholder (@+id/placeholder) et une valeur int de 12 ..

Ensuite, MyActivity.Java définit quelques vues ajoutées par programme (via le code):

int placeholderId = R.id.placeholder; // placeholderId==12
// returns *placeholder* which has id==12:
ViewGroup placeholder = (ViewGroup)this.findViewById(placeholderId);
for (int i=0; i<20; i++){
    TextView tv = new TextView(this.getApplicationContext());
    // One new TextView will also be assigned an id==12:
    tv.setId(i);
    placeholder.addView(tv);
}

Donc, placeholder et l’un de nos nouveaux TextViews ont tous les deux un id de 12! Mais ce n'est pas vraiment un problème si nous interrogeons les vues enfants de l'espace réservé:

// Will return a generated TextView:
 placeholder.findViewById(12);

// Whereas this will return the ViewGroup *placeholder*;
// as long as its R.id remains 12: 
Activity.this.findViewById(12);

*Pas si mal

510
CodeShane

Vous pouvez simplement utiliser la View.setId(integer) pour cela. Dans le XML, même si vous définissez un identifiant de chaîne, celui-ci est converti en un entier. Pour cette raison, vous pouvez utiliser n'importe quel entier (positif) pour le Views que vous ajoutez par programme.

Selon la documentation View

L'identifiant ne doit pas nécessairement être unique dans la hiérarchie de cette vue. L'identifiant doit être un nombre positif.

Vous pouvez donc utiliser n'importe quel entier positif, mais dans ce cas, il peut y avoir des vues avec des identifiants équivalents. Si vous souhaitez rechercher une vue dans la hiérarchie, un appel à setTag avec certains objets clés peut s'avérer utile.

Crédits à cette réponse .

6
Sander van't Veer

Oui, vous pouvez appeler setId(value) dans n'importe quelle vue avec une valeur entière (positive) de votre choix, puis la trouver dans le conteneur parent à l'aide de findViewById(value). Notez qu'il est valide d'appeler setId() avec la même valeur pour différentes vues frères, mais findViewById() ne renverra que la première.

5
dmon