2015-08-04 29 views
5

Come faccio a fare riferimento a un elemento XML successivo?Elemento xml di riferimento layout Android più avanti nel file

Ecco un caso d'uso specifico. Diciamo che ho un modulo con una LinearLayout di root, contenente LinearLayouts per più righe, ogni riga ha una o più aree di input del testo.

Ecco un'immagine di ciò che sto cercando. La prima immagine proviene dall'app di Venmo, la seconda è il rendering del seguente XML.

Example of Venmo The layout

Tale disposizione potrebbe essere la seguente:

<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 questo caso l'uso, riferimento in avanti è necassary al fine di impostare l'elemento attivo successivo. In questo modo, quando si preme il pulsante successivo sulla tastiera, verrà visualizzata la vista corretta. In questo esempio xml, senza lo nextFocusDown s, premendo next si passerebbe da un nome all'altro e non si passerebbe mai all'anno.

Tuttavia, se si tenta di compilare questo, si otterrà un errore:

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

Questo perché l'id month non è ancora stato inizializzato quando sto cercando di farvi riferimento, dato che è più tardi nel file. Come posso fare riferimento a un ID in xml che appare più avanti nel file?

+0

Questo è un self risposto alla domanda. Non ho trovato nulla che spiegasse questo, quindi ho pensato di farlo da solo. Suggerimenti per il miglioramento sono i benvenuti :) –

risposta

11

La soluzione più semplice è solo per sostituire

android:nextFocusDown="@id/month"

con

android:nextFocusDown="@+id/month"

Quando il compilatore sta analizzando il vostro XML per aggiungere l'ID di per R.java, si legge solo top in fondo. Quando hai @id/month, cerca tra gli ID esistenti e non riesce a trovarlo.

Tuttavia, se si esegue @+id/month, viene creato un nuovo ID e collegamenti a tale. Quando arriva a android:[email protected]+id/month nella vista mese reale, lo collega allo stesso id che abbiamo già creato.


Ciò fa apparire la domanda: se è possibile sostituire con @id/@+id/ e @+id/ funzionerà indipendentemente l'ordine degli elementi, perché nemmeno la briga di usare @id/?

Il motivo è se l'ID non esiste, @id/ genera un errore del compilatore, mentre @+id/ registra un avviso in fase di esecuzione.

considerare questo 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"/> 

Quando questo viene analizzato, viene creato un nuovo elemento id SOME_RANDOM_ID. Tuttavia, quando Android tenta di applicarlo in fase di runtime, non riesce a trovare un elemento con quell'id.Se si guarda a Logcat, vedrete questo:

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

messaggio Questo registro è sia difficile da trovare e difficile da debug. Un piccolo refuso in un @+id/ e avrai un bug che potrebbe essere incredibilmente difficile da eseguire il debug. Tuttavia, se avessimo fatto:

android:nextFocusDown="@id/SOME_RANDOM_ID"

Poi ci piacerebbe avere un errore di compilazione, qualcosa di simile:

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

Questo è molto più facile da trovare ed eseguire il debug.


tl; dr: È possibile utilizzare @+id/ invece di @id/ e sarete in grado di trasmettere riferimento, ma si noti che che possono fare piccoli errori di battitura incredibilmente difficile da eseguire il debug.

Potrebbe essere possibile utilizzare un RelativeLayout per rendere tutte le viste esistenti in ordine inverso nell'xml, ma mi sembra eccessivo.

0

Ho avuto lo stesso problema da poco e ho usato @ + id/my_new_id la prima volta ho fatto riferimento l'elemento e poi nel XML nella definizione dell'elemento, ho assegnato @ id/my_new_id alla Android: attributo id. Sembra che funzioni bene e non è necessario scrivere @ + id con lo stesso id più di una volta, evitando possibili avvisi.

Ad esempio:

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

... 

</LinearLayout> 

<ImageButton 
    android:id="@id/my_new_id" 
    ... /> 
Problemi correlati