212 votes

Comment attribuer un ID à une vue de manière programmatique ?

Dans un fichier XML, nous pouvons attribuer un ID à une vue comme suit android:id="@+id/something" et ensuite appeler findViewById() mais lorsque je crée une vue de manière programmatique, comment puis-je attribuer un ID ?

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

Quelqu'un peut-il me corriger ?

537voto

CodeShane Points 2233

Android id vue d'ensemble

Un Android id est un nombre entier couramment utilisé pour identifier les vues ; ce id peuvent être attribuées via XML (lorsque cela est possible) et via le code (de manière programmatique). id est le plus utile pour obtenir des références pour les éléments définis par XML View générées par un Inflater (par exemple en utilisant setContentView .)

Affecter id via XML

  • Ajouter un attribut de android:id="@+id/ somename " à votre vue.
  • Lorsque votre application est construite, le android:id se verra attribuer un unique int à utiliser dans le code.
  • Référencez votre android:id 's int dans le code en utilisant " R.id. somename" (en fait une constante.)
  • ce int peut changer d'une construction à l'autre donc ne jamais copier un identifiant de gen/ paquet.nom/ R.java il suffit d'utiliser " R.id. somename".
  • (Aussi, un id attribué à un Preference en XML n'est pas utilisé lorsque le Preference génère son View .)

Affecter id via le code (par programmation)

  • Réglage manuel id s en utilisant someView.setId( int );
  • Le site int doit être positif, mais est par ailleurs arbitraire - il peut être ce que vous voulez (continuez à lire si cela vous effraie).
  • Par exemple, si vous créez et numérotez plusieurs vues représentant des articles, vous pouvez utiliser leur numéro d'article.

Unicité de id s

  • XML -assigné id seront uniques.
  • Code assigné id s faire pas doivent être uniques
  • Code assigné id peuvent (théoriquement) entrer en conflit avec XML -assigné id s.
  • Ces conflits id n'auront aucune importance si elles sont interrogées correctement. (continuer à lire) .

Quand (et pourquoi) des conflits id n'ont pas d'importance

  • findViewById(int) va itérer en profondeur d'abord récursivement à travers la hiérarchie des vues à partir de la vue que vous spécifiez et retourner le premier View qu'il trouve avec une correspondance id .
  • Tant qu'il n'y a pas de code attribué id attribuées avant un id dans la hiérarchie, findViewById(R.id.somename) retournera toujours la vue définie par XML, donc id 'd.

Création dynamique de vues et affectation ID s

  • Dans le layout XML, définissez un ViewGroup avec id .

  • Comme un LinearLayout avec android:id="@+id/placeholder" .

  • Utilisez le code pour remplir l'espace réservé ViewGroup avec View s.

  • Si vous avez besoin ou si vous voulez, attribuez n'importe quel id qui conviennent à chaque vue.

  • Interrogez ces vues enfant en utilisant placeholder.findViewById(convenientInt) ;

  • Introduction de l'API 17 View.generateViewId() qui permet de générer un identifiant unique.

Si vous choisissez de conserver des références à vos points de vue autour de assurez-vous de les instancier avec getApplicationContext() et assurez-vous de mettre chaque référence à null dans onDestroy . Apparemment, qui fuit le site Activity (s'y accrocher après sa destruction) est un gaspillage :)

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

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

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

Ici, valeurs/ids.xml définit une id :

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

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

myViewGroup.setId(R.id.reservedNamedId);

Conflictuel id exemple

Pour plus de clarté, à l'aide d'un exemple obfusqué, examinons ce qui se passe lorsqu'il existe une id conflit 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 dernier build a attribué R.id.placeholder ( @+id/placeholder ) et int valeur de 12 ..

Suivant, MonActivité.java définit certaines vues ajoutées de manière programmatique (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);
}

Alors placeholder et l'un de nos nouveaux TextView ont tous deux un id de 12 ! Mais ce n'est pas vraiment un problème si nous interrogeons les vues enfant de placeholder :

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

*Not so bad

6voto

Sander van't Veer Points 3060

Vous pouvez simplement utiliser le View.setId(integer) pour cela. Dans le XML, même si vous définissez un identifiant de type String, celui-ci est converti en un nombre entier. C'est pourquoi vous pouvez utiliser n'importe quel nombre entier (positif) pour l'attribut Views que vous ajoutez de manière programmatique.

Selon View documentation

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

Donc vous pouvez utiliser n'importe quel nombre entier positif que vous voulez, mais dans ce cas il y a il peut y avoir des vues avec des identifiants équivalents. Si vous voulez rechercher une certaine vue dans la hiérarchie, l'appel à setTag avec certains objets clés peut être pratique.

Crédits à cette réponse .

5voto

dmon Points 20795

Oui, vous pouvez appeler setId(value) dans n'importe quelle vue avec la valeur entière (positive) de votre choix, puis retrouvez-le dans le conteneur parent en utilisant la commande findViewById(value) . Notez qu'il est valide d'appeler setId() avec la même valeur pour des vues différentes de la fratrie, mais findViewById() ne retournera que le premier.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X