2015-08-04 3 views
5

Wie referenziere ich ein späteres XML-Element?Android-Layout-Referenz XML-Element später in Datei

Hier ist ein spezifischer Anwendungsfall. Nehmen wir an, ich habe ein Formular mit einem Root-LinearLayout, das LinearLayouts für mehrere Zeilen enthält, wobei jede Zeile einen oder mehrere Texteingabebereiche hat.

Hier ist ein Bild von dem, was ich anstrebe. Das erste Bild stammt von Venmos App, das zweite ist ein Rendering des folgenden XML.

Example of Venmo The layout

Ein solches Layout könnte wie folgt aussehen:

<LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical"> 

    <LinearLayout 
     android:id="@+id/row_card_number" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:orientation="horizontal"> 

     <EditText 
      android:id="@+id/card_number" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:nextFocusDown="@id/month"/> 
    </LinearLayout> 

    <LinearLayout 
     android:id="@+id/row_date" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:orientation="horizontal"> 

     <EditText 
      android:id="@+id/month" 
      android:layout_height="wrap_content" 
      android:layout_width="100dp" 
      android:nextFocusDown="@id/year"/> 

     <EditText 
      android:id="@+id/year" 
      android:layout_height="wrap_content" 
      android:layout_width="match_parent"/> 
    </LinearLayout> 
</LinearLayout> 

In diesem Anwendungsfall vorwärts Referenzierung necassary, um die nächste Fokuselement einzustellen. Auf diese Weise wird beim Drücken der nächsten Taste auf der Tastatur die richtige Ansicht angezeigt. In diesem Beispiel xml, ohne die nextFocusDown s, würde die nächste drücken von Name zu Monat gehen, und nie zu Jahr gehen.

Wenn Sie jedoch versuchen, dies zu kompilieren, erhalten Sie eine Fehlermeldung erhalten:

Error:(18, 36) No resource found that matches the given name (at 'nextFocusDown' with value '@id/month').

Dies liegt daran, die ID month noch nicht initialisiert wurde, wenn ich es zu verweisen bin versucht, denn das ist, später in der Datei. Wie kann ich auf eine ID in XML verweisen, die später in der Datei angezeigt wird?

+0

Dies ist eine selbst beantworteten Frage. Ich habe nicht wirklich etwas gefunden, was das gut erklärt hat, also dachte ich, ich würde es selbst machen. Verbesserungsvorschläge sind willkommen :) –

Antwort

11

Die einfachste Lösung ist nur

android:nextFocusDown="@id/month"

mit

android:nextFocusDown="@+id/month"

zu ersetzen Wenn der Compiler Ihre XML-Parsing die IDs zu R.java hinzuzufügen, liest sie gerade oben nach unten. Wenn Sie @id/month haben, durchsucht es die vorhandenen IDs und findet sie nicht.

Wenn Sie jedoch @+id/month tun, erstellt es eine neue ID und verweist darauf. Wenn es in der aktuellen Monatsansicht zu android:[email protected]+id/month wird, verknüpft es es mit derselben ID, die wir bereits erstellt haben.


Dies bringt die Frage auf: Wenn Sie @id/ mit @+id/ ersetzen können, und @+id/ funktioniert unabhängig von der Reihenfolge der Elemente, die Mühe, warum auch @id/ zu benutzen?

Der Grund dafür ist, wenn die ID nicht existiert, wird einen Compilerfehler werfen, während @+id/ eine Warnung zur Laufzeit protokolliert.

Betrachten Sie dieses XML:

<EditText 
    android:id="@+id/month" 
    android:layout_height="wrap_content" 
    android:layout_width="100dp" 
    android:nextFocusDown="@+id/SOME_RANDOM_ID"/> 

<EditText 
    android:id="@+id/year" 
    android:layout_height="wrap_content" 
    android:layout_width="match_parent"/> 

Wenn diese analysiert wird, wird ein neues ID-Element SOME_RANDOM_ID erstellt. Wenn Android jedoch versucht, es zur Laufzeit anzuwenden, kann es kein Element mit dieser ID finden.Wenn Sie sich Logcat ansehen, sehen Sie Folgendes:

W/View﹕ couldn't find view with id 2131689604

Diese Protokollnachricht ist schwer zu finden und schwer zu debuggen. Ein kleiner Tippfehler in einem @+id/ und Sie werden einen Fehler haben, der unglaublich schwer zu debuggen sein könnte. hätten wir jedoch getan:

android:nextFocusDown="@id/SOME_RANDOM_ID"

Dann würden wir einen Compiler-Fehler, so etwas wie:

Error:(18, 36) No resource found that matches the given name (at 'nextFocusDown' with value '@id/SOME_RANDOM_ID').

Das ist viel einfacher zu finden und zu debuggen.


tl; dr: Sie können @+id/ anstelle von @id/ und Sie werden in der Lage sein, auf weiterleiten, aber beachten Sie, dass das können kleine Fehler unglaublich schwer zu debuggen.

Sie könnten ein RelativeLayout verwenden, um alle Ansichten in umgekehrter Reihenfolge in der XML-Datei zu erhalten, aber das scheint mir ein Overkill zu sein. vor kurzem

0

hatte ich das gleiche Problem und ich @ + id/my_new_id das erste Mal, dass ich das Element verwiesen wird und später in der XML in der Elementdefinition, ich zugewiesen @ id/my_new_id zum android: ID Attribut. Es scheint, es funktioniert gut und es ist nicht notwendig, @ + ID mit der gleichen ID mehr als einmal zu vermeiden, mögliche Warnungen zu vermeiden.

Zum Beispiel:

<LinearLayout 
    ... 
    android:layout_toLeftOf="@+id/my_new_id" 
    ... > 

... 

</LinearLayout> 

<ImageButton 
    android:id="@id/my_new_id" 
    ... /> 
Verwandte Themen