Come posso assegnare un ID a una vista a livello di codice?


202

In un file XML, possiamo assegnare un ID a una vista come android:id="@+id/something"e quindi chiamarefindViewById() , ma quando creo una vista a livello di , come posso assegnare un ID?

Penso che setId()non sia lo stesso dell'assegnazione predefinita. setId()è extra.

Qualcuno può correggermi?


Risposte:


521

idPanoramica di Android

Un Android idè un numero intero comunemente usato per identificare le viste; questo idpuò essere assegnato via XML (quando possibile) e via codice (programmaticamente). idÈ più utile per ottenere riferimenti per Views definiti da XML generati da un Inflater(come usando setContentView.)

Assegna idviaXML

  • Aggiungi un attributo di android:id="@+id/somename "alla tua vista.
  • Quando viene creata l'applicazione, android:idverrà assegnato un unico int per l'uso nel codice.
  • Riferimento tua android:ids' intvalore nel codice utilizzando "R.id. nomeacaso'(in modo efficace una costante.)
  • questo intpuò cambiare da build a build, quindi non copiare mai un ID da gen/package.name/ R.java, basta usare " R.id.somename".
  • (Inoltre, un idassegnato a un Preferencein XML non viene utilizzato quando Preferencegenera il suo View.)

Assegna idtramite codice (a livello di codice)

  • Impostare manualmente idusandosomeView.setId( int);
  • Il int deve essere positivo, ma è comunque arbitrario, infatti esso può essere quello che vuoi (continuate a leggere se questo è spaventoso.)
  • Ad esempio, se si creano e si numerano più viste che rappresentano articoli, è possibile utilizzare il loro numero di articolo.

Unicità di ids

  • XML-signed ids sarà unico.
  • Codice assegnato ids non non devono essere univoci
  • I messaggi assegnati in codice idpossono (teoricamente) XMLentrare in conflitto con i messaggi assegnati id.
  • Questi messaggi in conflitto idnon importeranno se interrogati correttamente (continua a leggere) .

Quando (e perché) i conflitti idnon contano

  • findViewById(int)eseguirà l'iterazione della profondità in modo ricorsivo attraverso la gerarchia della vista dalla vista specificata e restituirà la prima Viewche trova con una corrispondenza id.
  • Fintanto che non vi sono assegnazioni di codice idassegnate prima di un XML definito idnella gerarchia, findViewById(R.id.somename)verrà sempre restituita la vista definita in XML così id'd.

Creazione dinamica di viste e assegnazione di messaggi di posta IDelettronica

  • Nel layout XML, definire un vuoto ViewGroupcon id.
  • Come un LinearLayoutcon android:id="@+id/placeholder".
  • Usa il codice per popolare il segnaposto ViewGroupcon Views.
  • Se è necessario o desiderato, assegnare qualsiasi ids conveniente per ciascuna vista.
  • Interroga queste visualizzazioni figlio utilizzando placeholder.findViewById (convenientInt);

  • API 17 introdotta View.generateViewId()che consente di generare un ID univoco.

Se si sceglie di mantenere i riferimenti alle proprie visualizzazioni , accertarsi di crearle un'istanza getApplicationContext()e assicurarsi di impostare ogni riferimento su null in onDestroy. A quanto pare che perde il Activity(appeso su di esso dopo che è stato distrutto) è uno spreco .. :)

Prenota un XML android:idper l'uso nel codice

API 17 introdotta View.generateViewId() che genera un ID univoco.(Grazie a prendere-possibilità-apportare modifiche per averlo sottolineato.) *

Se il tuo ViewGroupnon può essere definito tramite XML (o non vuoi che lo sia) puoi riservare l'id tramite XML per assicurarti che rimanga unico:

Qui, valori / ids.xml definisce un'abitudine id:

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

Quindi, una volta creati il ​​ViewGroup o View, è possibile collegare l'id personalizzato

myViewGroup.setId(R.id.reservedNamedId);

idEsempio contrastante

Per chiarezza a titolo di esempio offuscante, esaminiamo cosa succede quando c'è un id conflitto dietro le quinte.

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>

Per simulare un conflitto, supponiamo che il nostro ultimo build abbia assegnato R.id.placeholder( @+id/placeholder) un intvalore di 12 ..

Successivamente, MyActivity.java definisce alcune visualizzazioni aggiunte a livello di codice (tramite codice):

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

Quindi, placeholderuno dei nostri nuovi ha TextViewentrambi id12! Ma questo non è davvero un problema se interroghiamo le visualizzazioni figlio del segnaposto:

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

*Non così male


9
Oltre a ciò, potrebbe essere utile che qualcuno nel codificare soluzioni simili sia a conoscenza di View.generateViewId () in API> 17 per ID non in conflitto
AllDayAmazing

Si noti che findViewByIdesegue una prima esplorazione approfondita, pertanto "Fintanto che nella gerarchia non sono presenti ID assegnati a codice assegnati sopra un ID definito in XML" non è tecnicamente corretto; è "prima" piuttosto che "sopra".
Karu,

Nelle versioni più recenti degli strumenti per sviluppatori Android, l'impostazione a livello di codice dell'ID su un valore arbitrario verrà contrassegnata come errore del compilatore. Il valore dovrebbe essere un ID risorsa effettivo.
ThomasW,

Credo che ciò sia avvenuto anche quando ho risposto cinque anni fa: ecco perché è stato necessario definire l'id personalizzato ids.xml. Per ID davvero arbitrari, utilizzare View.generateViewId()(API 17). (Per favore, chiarisci il tuo punto se l'ho perso.)
CodeShane

> (Inoltre, un ID assegnato a una preferenza in XML non viene utilizzato quando la preferenza genera la sua vista.) Molto interessato a questo. Il mio codice eredita da PreferenceDialogFragmentCompatesso sembra che gli ID di R.idnon corrispondano alla gerarchia della vista. In questo modo non riesco a trovare la vista per ID.
UrK,

6

Puoi semplicemente usare il View.setId(integer)per questo. Nell'XML, anche se stai impostando un ID String, questo viene convertito in un numero intero. Per questo motivo, è possibile utilizzare qualsiasi numero intero (positivo) per ilViews aggiunta a livello di codice.

Secondo la Viewdocumentazione

L'identificatore non deve essere univoco nella gerarchia di questa vista. L'identificatore dovrebbe essere un numero positivo.

Quindi puoi usare qualsiasi numero intero positivo che ti piace, ma in questo caso possono esserci alcune viste con ID equivalenti. Se vuoi cercare qualche vista nella gerarchia, può essere utile chiamare setTag con alcuni oggetti chiave.

Crediti per questa risposta .


5

Sì, puoi chiamare setId(value)in qualsiasi vista con qualsiasi valore intero (positivo) che ti piace e poi trovarlo nel contenitore padre usando findViewById(value). Si noti che è valido chiamare setId()con lo stesso valore per diverse viste di pari livello, ma findViewById()restituirà solo il primo.


1
Si noti che è necessario utilizzare un numero intero maggiore di zero.
Peter Ajtai,

sebbene findViewById (int) eseguirà un'iterazione ricorsiva attraverso la gerarchia della vista dalla vista specificata e restituirà la prima vista trovata con un ID corrispondente specificato nella prima risposta più accurato.
Aniket Thakur,

Sì, chiamare findViewByIdun antenato noto è una buona idea per motivi di prestazioni, ma non garantisce che troverà un figlio immediato se ce n'è uno con l'ID corretto.
Karu,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.