Spieghiamo le basi di LinearLayout — una ViewGroup di base in Android SDK per allineare gli elementi figli in una singola linea: verticalmente (LinearLayout.VERTICAL) o orizzontalmente (LinearLayout.HORIZONTAL). LinearLayout rimane il modo più semplice e veloce per costruire una riga di pulsanti, un elenco di impostazioni o un modulo di input quando la complessità del layout non supera i 5–10 elementi. Gli attributi layout_weight e orientation gestiscono la distribuzione dello spazio e la direzione. Specifica dettagliata — in LinearLayout API Reference.
Punti chiave
LinearLayout — uno dei primi ViewGroups in Android SDK (API Level 1), progettato per posizionare gli elementi figli sequenzialmente in una singola riga o colonna. Ogni nuovo elemento viene posizionato dopo il precedente e la direzione è impostata dall'attributo android:orientation. LinearLayout è il contenitore Android più semplice e prevedibile, rendendolo la scelta ideale per interfacce lineari: righe di pulsanti, elenchi di impostazioni con icona e testo, menu orizzontali.
Storicamente, LinearLayout è il primo ViewGroup che uno sviluppatore Android principiante incontra. Il suo vantaggio è la trasparenza: gli elementi figli vengono posizionati rigorosamente nell'ordine di dichiarazione, senza regole di posizionamento nascoste. A differenza di RelativeLayout, dove un elemento può essere legato a qualsiasi vicino, o ConstraintLayout con il suo sistema di vincoli, LinearLayout funziona secondo il principio "primo sinistra/alto, secondo dopo di esso, terzo dopo il secondo". Secondo Google I/O 2017, il 78% degli schermi nelle prime 1000 app di Google Play utilizza LinearLayout come contenitore principale o ausiliario.
La metrica principale di LinearLayout è LinearLayout.MeasureSpec — il sistema di gestione delle dimensioni. Con orientamento VERTICAL, la larghezza di ogni elemento è uguale alla larghezza del genitore (match_parent o fissa) e l'altezza è determinata dal contenuto o dall'attributo. Per HORIZONTAL è il contrario: l'altezza è uguale a quella del genitore, la larghezza dal contenuto. Se in una riga HORIZONTAL la larghezza totale degli elementi supera la larghezza del genitore, gli elementi possono uscire dallo schermo (se non si usa weight).
LinearLayout sovrascrive onMeasure e onLayout da ViewGroup. Con orientamento VERTICAL, onLayout posiziona gli elementi lungo l'asse Y: primo figlio — y=0, secondo — y=prev.bottom + divider.hidden, e così via. Con HORIZONTAL — lungo l'asse X. Il divisore viene impostato tramite android:divider e android:showDividers (beginning, middle, end). Il divisore può essere un colore, un drawable o una risorsa Shape personalizzata.
Orientamento — un attributo chiave di LinearLayout che determina la direzione del posizionamento degli elementi figli. android:orientation="vertical" dispone gli elementi dall'alto verso il basso; android:orientation="horizontal" — da sinistra a destra (o da destra a sinistra con localizzazione RTL). Se l'orientamento non è impostato, per impostazione predefinita viene utilizzato HORIZONTAL (sulle versioni precedenti) — ma la specifica esplicita è necessaria per un comportamento prevedibile.
android:gravity — allinea il contenuto all'interno di LinearLayout. Accetta combinazioni: top, bottom, left, right, center, center_horizontal, center_vertical, fill, clip_vertical, clip_horizontal. Un valore di gravity="center" per un layout VERTICAL centrerà tutti gli elementi orizzontalmente. android:layout_gravity — un attributo dell'elemento figlio che lo allinea all'interno del LinearLayout genitore. Esempio: un pulsante con layout_gravity="right" in un layout VERTICAL spingerà il pulsante verso il bordo destro.
La differenza: gravity — una proprietà del genitore (come i figli sono disposti al suo interno), layout_gravity — una proprietà del figlio (come si comporta all'interno del genitore). Confondere questi attributi è uno degli errori più comuni tra i principianti.
Per i layout HORIZONTAL con elementi di testo (TextView, Button, EditText), android:baselineAligned="true" è utile — allinea tutti i testi per la linea di base del carattere, indipendentemente dal padding, dimensione o altezza. Questo rende una riga con icona, titolo e descrizione visivamente ordinata: il testo non salta su e giù.
layout_weight — un attributo dell'elemento figlio di LinearLayout che determina quale parte dello spazio libero occuperà. Funziona solo nella direzione dell'orientamento (larghezza per HORIZONTAL, altezza per VERTICAL). Formula di calcolo: dimensione = dimensione propria + (spazio libero × (peso dell'elemento / somma di tutti i pesi)). Spazio libero = dimensione del genitore — somma di tutte le dimensioni proprie dei figli.
layout_weight è più efficiente delle dimensioni fisse per interfacce adattive. Ad esempio, se il pannello sinistro deve occupare il 30% dello schermo e il destro il 70%, impostare weight=3 e weight=7. Per un corretto funzionamento, la dimensione nella direzione viene solitamente impostata a 0dp (android:layout_width="0dp" per HORIZONTAL), quindi la dimensione propria dell'elemento è considerata zero e l'intera dimensione è determinata solo da weight. Questa è la raccomandazione standard di Google (Android Developers Guide, 2024).
Importante: i pesi vengono sommati per tutti gli elementi in LinearLayout, inclusi quelli senza weight impostato (il loro peso è considerato 0). Se un elemento ha weight=1 e un altro ha weight=2, il primo occuperà 1/3 dello spazio libero, il secondo — 2/3. weightSum (un attributo del genitore) consente di impostare la somma massima dei pesi — se la somma dei pesi dei figli è inferiore a weightSum, la differenza rimane come spazio vuoto.
Il modulo di login è composto da tre elementi: campo email (occupa 2/4), campo password (1/4) e pulsante (1/4) dell'altezza dello schermo. Tutti e tre gli elementi con weight funzionano solo in orientamento VERTICAL per altezza.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<EditText
android:id="@+id/email"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:hint="Email" />
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:hint="Password"
android:inputType="textPassword" />
<Button
android:id="@+id/login_button"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="Accedi" />
</LinearLayout>
L'altezza di ogni elemento = (parent_height — padding) × (weight / sumWeights). email ottiene 2/4 dell'altezza, password e pulsante — 1/4 ciascuno. Tutti height=0dp, quindi la dimensione propria non viene considerata — funziona solo weight.
Un pannello con tre pulsanti: icona indietro (wrap_content), titolo (riempire il resto) e icona menu (wrap_content). weight per il titolo = 1, pulsanti senza weight.
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="56dp"
android:gravity="center_vertical">
<ImageButton
android:id="@+id/btn_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_arrow_back" />
<TextView
android:id="@+id/toolbar_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Titolo"
android:textSize="18sp" />
<ImageButton
android:id="@+id/btn_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_more_vert" />
</LinearLayout>
I pulsanti indietro e menu occupano esattamente lo spazio necessario per l'icona. Il titolo (TextView) con width=0dp e weight=1 si estende su tutto lo spazio rimanente tra di loro. gravity="center_vertical" allinea tutti gli elementi verticalmente al centro.
Una scheda prodotto: riga orizzontale (immagine + blocco di testo verticale). LinearLayout esterno HORIZONTAL, interno — VERTICAL per titolo, descrizione e prezzo.
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:src="@drawable/product_image"
android:scaleType="centerCrop" />
<LinearLayout
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="12dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nome prodotto"
android:textStyle="bold"
android:textSize="16sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Breve descrizione del prodotto in due righe"
android:textSize="14sp"
android:textColor="@color/gray" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1.299 RUB"
android:textSize="18sp"
android:textColor="@color/accent" />
</LinearLayout>
</LinearLayout>
Immagine a sinistra (80×80dp), a destra — un blocco verticale di tre righe di testo. Il LinearLayout interno ha weight=1, quindi occupa tutto lo spazio rimanente dopo l'immagine. Questo è un pattern classico di scheda di elenco che si trova in migliaia di applicazioni.
Il principale svantaggio di LinearLayout — la necessità di contenitori annidati per layout complessi. Se è necessario disporre gli elementi in una griglia 2×2 o creare una riga con allineamento su entrambi i bordi, sono necessari almeno 2–3 livelli di annidamento. Ogni livello di LinearLayout aggiunge 2 passaggi di onMeasure, che su dispositivi deboli porta a ritardi notevoli durante il rendering.
Secondo Android Performance Blog (Google, 2017), ogni livello aggiuntivo di annidamento aumenta il tempo di layout di 30–50 μs. Per un elenco di 20 elementi con 3 livelli di annidamento, il ritardo può raggiungere 3 ms per elemento — questo è un jank notevole durante lo scorrimento. ConstraintLayout risolve questo problema attraverso una gerarchia piatta, sostituendo 3–4 LinearLayout annidati con un singolo contenitore di vincoli.
Raccomandazione: utilizzare LinearLayout per layout lineari semplici (fino a 10 elementi, un livello di annidamento). Per schede di elenco, moduli con allineamento diverso e schermi con struttura a tabella, scegliere ConstraintLayout. Per elementi ripetitivi in RecyclerView, utilizzare ConstraintLayout nel file di layout dell'elemento — questo è critico per le prestazioni di scorrimento.
Domande frequenti
Il motivo più comune — la dimensione nella direzione non è impostata a 0dp. Per il layout HORIZONTAL è necessario android:layout_width="0dp", per VERTICAL — android:layout_height="0dp". Se l'elemento ha wrap_content o match_parent, weight potrebbe non funzionare o dare risultati imprevisti. Il secondo motivo — weightSum sul genitore è inferiore alla somma dei pesi dei figli. Il terzo — utilizzare match_parent su un elemento figlio nella direzione opposta.
layout_weight viene impostato su ogni elemento figlio e determina la sua parte dello spazio libero. weightSum — un attributo del LinearLayout genitore che imposta la somma massima dei pesi. Per impostazione predefinita, weightSum = somma di tutti i layout_weight dei figli. Se si imposta weightSum = 3 e i figli hanno weight=1, ciascuno occuperà 1/3. Se ci sono solo due figli con weight=1, il restante 1/3 sarà vuoto. weightSum è comodo per fissare le proporzioni senza ricalcolo quando si aggiungono/rimuovono elementi.
Per impostazione predefinita non ci sono spazi — gli elementi sono posizionati adiacenti. Se compaiono spazi, controllare: android:divider e android:showDividers sul genitore, android:layout_margin sugli elementi figli. Inoltre, android:weightSum può influenzare — se gli elementi usano weight, potrebbe rimanere spazio vuoto tra di loro a causa di un calcolo errato. Per spazi zero, impostare tutti i margini dei figli a 0dp e rimuovere il divisore.
Per layout semplici unidirezionali (1–5 elementi in una riga/colonna) LinearLayout è leggermente più veloce — non spreca risorse nel calcolo dei vincoli. Per layout complessi (più di 5 elementi, griglie, diversi tipi di allineamento) ConstraintLayout è più veloce perché utilizza una gerarchia piatta invece di LinearLayout annidati. Secondo i test di Google (Android Performance Blog), ConstraintLayout vince su layout che richiedono 3+ livelli di annidamento di LinearLayout.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche