Wie kann ich einer Ansicht programmgesteuert eine ID zuweisen?


202

In einer XML-Datei können wir einer Ansicht wie eine ID zuweisen android:id="@+id/something"und dann aufrufen. findViewById()Wie kann ich beim programmgesteuerten Erstellen einer Ansicht eine ID zuweisen?

Ich denke, das setId()ist nicht dasselbe wie die Standardzuweisung. setId()ist extra.

Kann mich jemand korrigieren?


Antworten:


521

Android idÜbersicht

Ein Android idist eine Ganzzahl, die häufig zum Identifizieren von Ansichten verwendet wird. Dies idkann über XML (wenn möglich) und über Code (programmgesteuert) zugewiesen werden. Dies idist am nützlichsten, um Referenzen für XML-definierte Views zu erhalten, die von einem generiert wurden Inflater(z. B. mithilfe von setContentView.).

Zuweisen idüberXML

  • Fügen android:id="@+id/Sie "Ihrer Ansicht ein Attribut mit einem Namen hinzu .
  • Wenn Ihre Anwendung erstellt wird, android:idwird der eine eindeutige Funktion int zur Verwendung im Code zugewiesen .
  • Eingeben Ihres android:id‚s - intWert in Code‚ R.id.somename‘(effektiv eine Konstante.)
  • Dies intkann sich von Build zu Build ändern. Kopieren Sie daher niemals eine ID aus gen/package.name/ R.java. Verwenden R.id.Sie einfach " somename".
  • (Außerdem wird ein in XML idzugewiesenes Preferencenicht verwendet, wenn das Preferenceseine generiert View.)

Zuweisung idper Code (programmgesteuert)

  • Manuelles Setzen von ids mit someView.setId(int);
  • Das intmuss positiv sein, ist aber ansonsten willkürlich - es kann alles sein, was Sie wollen (lesen Sie weiter, wenn dies schrecklich ist.)
  • Wenn Sie beispielsweise mehrere Ansichten erstellen und nummerieren, die Elemente darstellen, können Sie deren Elementnummer verwenden.

Einzigartigkeit von ids

  • XML-zugewiesene ids werden einzigartig sein.
  • Code-zugewiesene ids müssen nicht eindeutig sein
  • Code-zugewiesene ids können (theoretisch) mit XML-zugewiesenen ids in Konflikt stehen .
  • Diese widersprüchlichen ids spielen keine Rolle, wenn sie korrekt abgefragt werden (lesen Sie weiter) .

Wann (und warum) Konflikte idkeine Rolle spielen

  • findViewById(int)iteriert die Tiefe zuerst rekursiv durch die Ansichtshierarchie aus der von Ihnen angegebenen Ansicht und gibt die erste gefundene AnsichtView mit einer Übereinstimmung zurück id.
  • Solange idvor einem idin der Hierarchie definierten XML kein Code zugewiesen ist , findViewById(R.id.somename)wird immer die XML-definierte Ansicht zurückgegeben id.

Ansichten dynamisch erstellen und IDs zuweisen

  • Definieren Sie in Layout-XML ein Leerzeichen ViewGroupmit id.
  • Wie ein LinearLayoutmit android:id="@+id/placeholder".
  • Verwenden Sie Code, um den Platzhalter ViewGroupmit Views zu füllen.
  • Wenn Sie möchten oder möchten, weisen Sie idjeder Ansicht ein beliebiges s zu.
  • Fragen Sie diese untergeordneten Ansichten mit placeholder.findViewById (bequemeInt) ab.

  • API 17 wurde eingeführt View.generateViewId(), mit der Sie eine eindeutige ID generieren können.

Wenn Sie Verweise auf Ihre Ansichten beibehalten möchten, müssen Sie diese instanziieren getApplicationContext()und jeden Verweis auf null in setzen onDestroy. Offenbar undichte das Activity(hanging auf sie nach zerstört wird) ist verschwenderisch .. :)

Reservieren Sie ein XML android:idzur Verwendung im Code

API 17 eingeführt View.generateViewId() , die eine eindeutige ID generiert. (Dank an das Risiko, Änderungen vorzunehmen, um darauf hinzuweisen.) *

Wenn Sie ViewGroupnicht über XML definiert werden können (oder nicht möchten), können Sie die ID über XML reservieren, um sicherzustellen, dass sie eindeutig bleibt:

Hier definiert values ​​/ ids.xml eine benutzerdefinierte Funktion id:

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

Sobald die ViewGroup oder View erstellt wurde, können Sie die benutzerdefinierte ID anhängen

myViewGroup.setId(R.id.reservedNamedId);

Widersprüchliches idBeispiel

Lassen Sie uns zur Verdeutlichung anhand eines verschleierten Beispiels untersuchen, was passiert, wenn idhinter den Kulissen ein Konflikt auftritt.

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>

Um einen Konflikt zu simulieren, nehmen wir an, unser letzter Build hat R.id.placeholder( @+id/placeholder) den intWert 12 .. zugewiesen .

Als Nächstes definiert MyActivity.java einige hinzugefügte Ansichten programmgesteuert (über 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);
}

Also placeholderund einer unserer neuen hat TextViewbeide einen idvon 12! Dies ist jedoch kein wirkliches Problem, wenn wir die untergeordneten Ansichten des Platzhalters abfragen:

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

*Nicht so schlecht


9
Darüber hinaus kann es für jemanden, der ähnliche Lösungen codiert, nützlich sein, View.generateViewId () in API> 17 für nicht widersprüchliche IDs zu kennen
AllDayAmazing

Beachten Sie, dass findViewByIdeine Tiefenerkundung durchgeführt wird. "Solange keine Code-zugewiesenen IDs über einer XML-definierten ID in der Hierarchie zugewiesen sind", ist technisch nicht korrekt. Es ist "vor" und nicht "über".
Karu

In neueren Versionen der Android-Entwicklertools wird das programmgesteuerte Festlegen der ID auf einen beliebigen Wert als Compilerfehler gekennzeichnet. Es wird erwartet, dass der Wert eine tatsächliche Ressourcen-ID ist.
ThomasW

Ich glaube, das war sogar der Fall, als ich dies vor fünf Jahren beantwortete - deshalb mussten die benutzerdefinierten IDs in definiert werden ids.xml. Verwenden Sie für wirklich beliebige IDs View.generateViewId()(API 17). (Bitte klären Sie Ihren Punkt, wenn ich ihn verpasst habe.)
CodeShane

> (Außerdem wird eine einer Voreinstellung in XML zugewiesene ID nicht verwendet, wenn die Voreinstellung ihre Ansicht generiert.) Sehr interessiert daran. Mein Code erbt PreferenceDialogFragmentCompatdavon, als ob IDs von R.idnicht mit der Ansichtshierarchie übereinstimmen. Auf diese Weise kann ich die Ansicht nicht anhand der ID finden.
UrK

6

Sie können das einfach dafür verwenden View.setId(integer). Obwohl Sie im XML eine String-ID festlegen, wird diese in eine Ganzzahl konvertiert. Aus diesem Grund können Sie eine beliebige (positive) Ganzzahl für das Views programmgesteuerte Hinzufügen verwenden.

Laut ViewDokumentation

Der Bezeichner muss in der Hierarchie dieser Ansicht nicht eindeutig sein. Die Kennung sollte eine positive Zahl sein.

Sie können also eine beliebige positive Ganzzahl verwenden. In diesem Fall kann es jedoch einige Ansichten mit entsprechenden IDs geben. Wenn Sie nach einer Ansicht in einer Hierarchie suchen möchten, kann es hilfreich sein, setTag mit einigen Schlüsselobjekten aufzurufen.

Dank an diese Antwort .


5

Ja, Sie können setId(value)jede Ansicht mit einem beliebigen (positiven) Ganzzahlwert aufrufen und ihn dann im übergeordneten Container mit finden findViewById(value). Beachten Sie, dass es gültig ist, setId()für verschiedene Geschwisteransichten mit demselben Wert aufzurufen , aber findViewById()nur die erste zurückgibt.


1
Beachten Sie, dass Sie eine Ganzzahl größer als Null verwenden müssen.
Peter Ajtai

obwohl findViewById (int) aus der Sicht rekursiv durch die Ansichtshierarchie durchlaufen werden Sie den ersten Blick findet es mit einem passenden ID angeben und zurück in der 1. Antwort angegeben ist am genauesten.
Aniket Thakur

Ja, findViewByIdeinen bekannten Vorfahren anzurufen ist aus Leistungsgründen eine gute Idee, aber es garantiert nicht, dass ein unmittelbares Kind gefunden wird, wenn es eines mit der richtigen ID gibt.
Karu
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.