Layout nelle visualizzazioni
Un layout definisce la struttura di un'interfaccia utente nella tua app, ad esempio in un'attività. Tutti gli elementi nel
layout sono creati utilizzando una gerarchia di
oggetti View e
ViewGroup. Un View di solito disegna qualcosa che l'utente può vedere e con cui può interagire. Un ViewGroup è un contenitore invisibile che definisce
la struttura del layout per View e altri oggetti ViewGroup, come mostrato nella Figura 1.
Gli oggetti View sono spesso chiamati widget e possono essere una delle
molte sottoclassi, ad esempio
Button o
TextView. Gli oggetti
ViewGroup sono in genere chiamati layout e possono essere di molti tipi diversi che forniscono una struttura di layout diversa, ad esempio
LinearLayout
o
ConstraintLayout.
Puoi dichiarare un layout in due modi:
- Dichiara gli elementi UI in XML. Android fornisce un vocabolario XML semplice che corrisponde alle classi e alle sottoclassi
View, come quelle per widget e layout. Puoi anche utilizzare l'editor layout di Android Studio per creare il layout XML utilizzando un'interfaccia di trascinamento. - Istanziare gli elementi del layout in fase di runtime. La tua app può creare
oggetti
VieweViewGroupe manipolarne le proprietà in modo programmatico.
La dichiarazione della UI in XML consente di separare la presentazione dell'app dal codice che ne controlla il comportamento. L'utilizzo di file XML semplifica anche la fornitura di layout diversi per dimensioni e orientamenti dello schermo diversi. Questo argomento è trattato più nel dettaglio in Supportare diverse dimensioni dello schermo.
Il framework Android ti offre la flessibilità di utilizzare uno o entrambi questi metodi per creare l'interfaccia utente della tua app. Ad esempio, puoi dichiarare i layout predefiniti della tua app in XML e poi modificarli in fase di runtime.
Scrivi l'XML
Utilizzando il vocabolario XML di Android, puoi progettare rapidamente i layout dell'interfaccia utente e gli elementi dello schermo che contengono, nello stesso modo in cui crei pagine web in HTML con una serie di elementi nidificati.
Ogni file di layout deve contenere esattamente un elemento radice, che deve essere un oggetto View o ViewGroup. Dopo aver definito l'elemento
radice, puoi aggiungere altri oggetti o widget di layout come elementi secondari per
creare gradualmente una gerarchia View che definisce il layout. Ad esempio, ecco un layout XML che utilizza un LinearLayout verticale per contenere un TextView e un Button:
<?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" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a Button" /> </LinearLayout>
Dopo aver dichiarato il layout in XML, salva il file con l'estensione
.xml nella directory res/layout/ del progetto Android in modo che venga compilato correttamente.
Per ulteriori informazioni sulla sintassi di un file XML di layout, consulta Risorsa di layout.
Carica la risorsa XML
Quando compili l'app, ogni file di layout XML viene compilato in una risorsa
View. Carica la risorsa di layout nell'implementazione del callback
Activity.onCreate()
della tua app. Per farlo, chiama
setContentView(),
passando il riferimento alla risorsa di layout nel modulo:
R.layout.layout_file_name. Ad esempio, se il layout XML
è salvato come main_layout.xml, caricalo per il tuo
Activity come segue:
Kotlin
fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) setContentView(R.layout.main_layout) }
Java
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_layout); }
Il framework Android chiama il metodo di callback onCreate() nel
tuo Activity quando viene avviato Activity. Per maggiori
informazioni sui cicli di vita delle attività, consulta
Introduzione alle
attività.
Attributi
Ogni oggetto View e ViewGroup supporta una propria
varietà di attributi XML. Alcuni attributi sono specifici di un oggetto View. Ad esempio, TextView supporta l'attributo textSize. Tuttavia, questi attributi vengono ereditati anche da tutti gli oggetti View
che estendono questa classe. Alcuni sono comuni a tutti gli oggetti View, perché vengono ereditati dalla classe View radice, come l'attributo id. Gli altri attributi sono considerati parametri
di layout, ovvero attributi che descrivono determinati orientamenti del layout
dell'oggetto View, come definito dall'oggetto
ViewGroup principale.
ID
A qualsiasi oggetto View può essere associato un ID intero per
identificare in modo univoco l'oggetto View all'interno dell'albero. Quando l'app viene
compilata, questo ID viene indicato come numero intero, ma in genere viene assegnato
nel file XML di layout come stringa nell'attributo id. Si tratta di un
attributo XML comune a tutti gli oggetti View ed è definito dalla
classe View. Lo usi molto spesso. La sintassi per un ID all'interno di un tag XML è la seguente:
android:id="@+id/my_button"
Il simbolo @ all'inizio della stringa indica che
il parser XML analizza ed espande il resto della stringa ID e la identifica come
una risorsa ID. Il simbolo più (+) indica che si tratta di un nuovo nome di risorsa
che deve essere creato e aggiunto alle risorse nel file R.java.
Il framework Android offre molte altre risorse ID. Quando fai riferimento a un ID risorsa Android, non hai bisogno del simbolo più, ma devi aggiungere lo spazio dei nomi del pacchetto android nel seguente modo:
android:id="@android:id/empty"
Lo spazio dei nomi del pacchetto android indica che stai facendo riferimento
a un ID della classe di risorse android.R anziché alla classe di risorse
locale.
Per creare viste e farvi riferimento dalla tua app, puoi utilizzare un pattern comune come segue:
- Definisci una visualizzazione nel file di layout e assegnale un ID univoco, come nell'esempio seguente:
<Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/my_button_text"/>
- Crea un'istanza dell'oggetto vista e acquisiscila dal layout,
in genere nel metodo
onCreate(), come mostrato nell'esempio seguente:Kotlin
val myButton: Button = findViewById(R.id.my_button)
Java
Button myButton = (Button) findViewById(R.id.my_button);
La definizione degli ID per gli oggetti di visualizzazione è importante quando si crea un
RelativeLayout.
In un layout relativo, le visualizzazioni di pari livello possono definire il proprio layout rispetto a un'altra visualizzazione di pari livello, a cui viene fatto riferimento tramite l'ID univoco.
Un ID non deve essere univoco in tutto l'albero, ma deve esserlo nella parte dell'albero in cui esegui la ricerca. Spesso si tratta dell'intero albero, quindi è meglio renderlo univoco, se possibile.
Parametri di layout
Gli attributi di layout XML denominati layout_something definiscono
i parametri di layout per View appropriati per
ViewGroup in cui si trova.
Ogni classe ViewGroup implementa una classe nidificata che estende
ViewGroup.LayoutParams.
Questa sottoclasse contiene tipi di proprietà che definiscono le dimensioni e la posizione di ogni
visualizzazione secondaria, in base al gruppo di visualizzazioni. Come mostrato nella figura 2, il gruppo di visualizzazione principale definisce i parametri di layout per ogni visualizzazione secondaria, incluso il gruppo di visualizzazione secondario.
Ogni sottoclasse LayoutParams ha una propria sintassi per impostare i valori. Ogni elemento secondario deve definire un LayoutParams appropriato per il relativo elemento principale, anche se potrebbe definire un LayoutParams diverso per i propri elementi secondari.
Tutti i gruppi di visualizzazioni includono larghezza e altezza, utilizzando layout_width
e layout_height, e ogni visualizzazione deve definirle. Molti
LayoutParams includono margini e bordi facoltativi.
Puoi specificare larghezza e altezza con misure esatte, ma ti sconsigliamo di farlo spesso. Più spesso, utilizzi una di queste costanti per impostare la larghezza o l'altezza:
wrap_content: indica alla visualizzazione di dimensionarsi in base alle dimensioni richieste dai contenuti.match_parent: indica alla visualizzazione di diventare grande quanto il gruppo di visualizzazioni padre lo consente.
In generale, non consigliamo di specificare la larghezza e l'altezza di un layout utilizzando
unità assolute come i pixel. Un approccio migliore è l'utilizzo di misure relative,
come le unità di pixel indipendenti dalla densità (dp), wrap_content o
match_parent, perché consente alla tua app di essere visualizzata correttamente su una
varietà di dimensioni dello schermo del dispositivo. I tipi di misurazione accettati sono definiti nella
risorsa di layout.
Posizione del layout
Una vista ha una geometria rettangolare. Ha una posizione, espressa come una coppia di coordinate sinistra e superiore, e due dimensioni, espresse come larghezza e altezza. L'unità per la posizione e le dimensioni è il pixel.
Puoi recuperare la posizione di una visualizzazione richiamando i metodi
getLeft()
e
getTop().
Il primo restituisce la coordinata sinistra (x) del rettangolo che rappresenta
la visualizzazione. Quest'ultima restituisce la coordinata superiore (y) del rettangolo
che rappresenta la visualizzazione. Questi metodi restituiscono la posizione della visualizzazione rispetto
al relativo elemento principale. Ad esempio, se getLeft() restituisce 20, significa che la
visualizzazione si trova a 20 pixel a destra del bordo sinistro del relativo
elemento padre diretto.
Inoltre, esistono metodi pratici per evitare calcoli non necessari:
ovvero
getRight()
e
getBottom().
Questi metodi restituiscono le coordinate dei bordi destro e inferiore del
rettangolo che rappresenta la visualizzazione. Ad esempio, chiamare getRight() è
simile al seguente calcolo: getLeft() + getWidth().
Dimensioni, spaziatura interna e margini
Le dimensioni di una visualizzazione sono espresse con una larghezza e un'altezza. Una visualizzazione ha due coppie di valori di larghezza e altezza.
La prima coppia è nota come larghezza misurata e
altezza misurata. Queste dimensioni definiscono le dimensioni che una visualizzazione deve avere
all'interno del relativo elemento padre. Puoi ottenere le dimensioni misurate chiamando
getMeasuredWidth()
e
getMeasuredHeight().
La seconda coppia è nota come larghezza e altezza o, a volte, come
larghezza disegno e altezza disegno. Queste dimensioni definiscono le
dimensioni effettive della visualizzazione sullo schermo, al momento del disegno e dopo il layout. Questi
valori potrebbero, ma non devono, differire dalla larghezza e dall'altezza misurate. Puoi
ottenere la larghezza e l'altezza chiamando
getWidth()
e
getHeight().
Per misurarne le dimensioni, una visualizzazione tiene conto del relativo padding. Il padding
è espresso in pixel per le parti sinistra, superiore, destra e inferiore della visualizzazione.
Puoi utilizzare il padding per compensare i contenuti della visualizzazione di un numero specifico di
pixel. Ad esempio, un padding a sinistra di due sposta il contenuto della visualizzazione di due pixel
a destra del bordo sinistro. Puoi impostare il padding utilizzando il metodo
setPadding(int, int, int, int)
e interrogarlo chiamando
getPaddingLeft(),
getPaddingTop(),
getPaddingRight(),
e
getPaddingBottom().
Sebbene una visualizzazione possa definire un padding, non supporta i margini. Tuttavia,
i gruppi di visualizzazione supportano i margini. Per saperne di più, consulta
ViewGroup e
ViewGroup.MarginLayoutParams.
Per ulteriori informazioni sulle dimensioni, consulta la sezione Dimensione.
Oltre a impostare margini e spaziatura interna a livello di programmazione, puoi impostarli anche nei layout XML, come mostrato nell'esempio seguente:
<?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" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="16dp" android:padding="8dp" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:paddingBottom="4dp" android:paddingEnd="8dp" android:paddingStart="8dp" android:paddingTop="4dp" android:text="Hello, I am a Button" /> </LinearLayout>
L'esempio precedente mostra l'applicazione di margini e spaziatura interna. TextView ha margini e spaziatura interna uniformi applicati su tutti i lati, mentre Button mostra come applicarli in modo indipendente a bordi diversi.
Layout comuni
Ogni sottoclasse della classe ViewGroup fornisce un modo unico per
visualizzare le visualizzazioni che vi sono nidificate. Il tipo di layout più flessibile e quello
che fornisce gli strumenti migliori per mantenere la gerarchia del layout poco profonda è
ConstraintLayout.
Di seguito sono riportati alcuni dei tipi di layout comuni integrati nella piattaforma Android.
Organizza i relativi elementi secondari in una singola riga orizzontale o verticale e crea una barra di scorrimento se la lunghezza della finestra supera la lunghezza dello schermo.
Creare elenchi dinamici
Quando i contenuti del layout sono dinamici o non predeterminati, puoi utilizzare
RecyclerView o
una sottoclasse di
AdapterView.
RecyclerView è in genere l'opzione migliore, perché utilizza la memoria
in modo più efficiente rispetto a AdapterView.
I layout comuni possibili con RecyclerView e
AdapterView includono:
RecyclerView offre più possibilità e
l'opzione per
creare un gestore
di layout personalizzato.
Riempi una visualizzazione adattatore con i dati
Puoi compilare un
AdapterView
come ListView
o
GridView associando l'istanza AdapterView a un
Adapter,
che recupera i dati da un'origine esterna e crea un View
che rappresenta ogni voce di dati.
Android fornisce diverse sottoclassi di Adapter utili
per recuperare diversi tipi di dati e creare visualizzazioni per un
AdapterView. I due adattatori più comuni sono:
ArrayAdapter- Utilizza questo adattatore quando l'origine dati è un array. Per impostazione predefinita,
ArrayAdaptercrea una visualizzazione per ogni elemento dell'array chiamandotoString()su ogni elemento e inserendo i contenuti in unTextView.Ad esempio, se hai un array di stringhe che vuoi visualizzare in un
ListView, inizializza un nuovoArrayAdapterutilizzando un costruttore per specificare il layout per ogni stringa e l'array di stringhe:Kotlin
val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray)
Java
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray);
Gli argomenti per questo costruttore sono i seguenti:
- La tua app
Context - Il layout che contiene un
TextViewper ogni stringa dell'array - L'array di stringhe
Quindi chiama
setAdapter()sul tuoListView:Kotlin
val listView: ListView = findViewById(R.id.listview) listView.adapter = adapter
Java
ListView listView = (ListView) findViewById(R.id.listview); listView.setAdapter(adapter);
Per personalizzare l'aspetto di ogni elemento, puoi eseguire l'override del metodo
toString()per gli oggetti nell'array. In alternativa, per creare una visualizzazione per ogni elemento diverso daTextView, ad esempio se vuoi unImageViewper ogni elemento dell'array, estendi la classeArrayAdaptered esegui l'override digetView()per restituire il tipo di visualizzazione che vuoi per ogni elemento. - La tua app
SimpleCursorAdapter- Utilizza questo adattatore quando i dati provengono da un
Cursor. Quando utilizziSimpleCursorAdapter, specifica un layout da utilizzare per ogni riga diCursore le colonne diCursorche vuoi inserire nelle visualizzazioni del layout che preferisci. Ad esempio, se vuoi creare un elenco di nomi e numeri di telefono delle persone, puoi eseguire una query che restituisce unCursorcontenente una riga per ogni persona e colonne per i nomi e i numeri. Poi crea un array di stringhe che specifica le colonne diCursorche vuoi nel layout per ogni risultato e un array di numeri interi che specifica le visualizzazioni corrispondenti in cui devono essere inserite le colonne:Kotlin
val fromColumns = arrayOf(ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER) val toViews = intArrayOf(R.id.display_name, R.id.phone_number)
Java
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}; int[] toViews = {R.id.display_name, R.id.phone_number};
Quando crei un'istanza di
SimpleCursorAdapter, passa il layout da utilizzare per ogni risultato,Cursorcontenente i risultati e questi due array:Kotlin
val adapter = SimpleCursorAdapter(this, R.layout.person_name_and_number, cursor, fromColumns, toViews, 0) val listView = getListView() listView.adapter = adapter
Java
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.person_name_and_number, cursor, fromColumns, toViews, 0); ListView listView = getListView(); listView.setAdapter(adapter);
SimpleCursorAdaptercrea quindi una visualizzazione per ogni riga diCursorutilizzando il layout fornito inserendo ogni elementofromColumnsnella visualizzazionetoViewscorrispondente.
Se nel corso della vita della tua app modifichi i dati sottostanti letti dall'adattatore, chiama
notifyDataSetChanged().
In questo modo, la visualizzazione allegata viene avvisata che i dati sono stati modificati e si aggiorna.
Gestire gli eventi di clic
Puoi rispondere agli eventi di clic su ogni elemento di un AdapterView
implementando l'interfaccia
AdapterView.OnItemClickListener. Ad esempio:
Kotlin
listView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id -> // Do something in response to the click. }
Java
// Create a message handling object as an anonymous class. private OnItemClickListener messageClickedHandler = new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { // Do something in response to the click. } }; listView.setOnItemClickListener(messageClickedHandler);
Risorse aggiuntive
Scopri come vengono utilizzati i layout nell'app demo Sunflower su GitHub.


