Spieghiamo l'essenza di RelativeLayout — un ViewGroup in Android SDK per posizionare elementi figli relativamente tra loro o rispetto al contenitore genitore. A differenza di LinearLayout, che dispone gli elementi rigorosamente in sequenza, RelativeLayout consente di posizionare qualsiasi elemento a sinistra, destra, sopra, sotto o centrato rispetto a qualsiasi altro elemento tramite il suo ID. Questo rende RelativeLayout comodo per layout sovrapposti e complessi senza annidamento. Le regole di base sono descritte nella documentazione di Android Developers.
Punti chiave
RelativeLayout — un ViewGroup introdotto in Android SDK a partire da API Level 1, che posiziona gli elementi figli tramite regole dichiarative (layout rules) rispetto al genitore o ad altri elementi figli. Ogni regola viene impostata tramite un attributo XML come android:layout_above, android:layout_below, android:layout_toLeftOf con il valore dell'ID dell'elemento target.
Prima di RelativeLayout, gli sviluppatori dovevano usare LinearLayout annidati per ogni posizionamento non standard — ciò portava ad annidamenti profondi e rendering lento. RelativeLayout ha risolto questo problema offrendo un posizionamento relativo a un singolo livello gerarchico. Tuttavia, la sua flessibilità è limitata rispetto al moderno ConstraintLayout: RelativeLayout non supporta catene, barriere, guide o dimensioni percentuali.
RelativeLayout ha due caratteristiche chiave: un singolo passaggio onMeasure (a differenza di LinearLayout con weight, che richiede due passaggi) e dipendenza dall'ordine di dichiarazione — se l'elemento A fa riferimento all'elemento B e B viene dichiarato dopo A, B deve avere una dimensione nota al momento della misurazione di A. Secondo la Guida per sviluppatori Android (2024), RelativeLayout esegue la misurazione in un unico passaggio se tutte le regole fanno riferimento a elementi già misurati. Altrimenti, è necessario un secondo passaggio, che riduce le prestazioni.
RelativeLayout è giustificato per layout semplici con 3–7 elementi dove è richiesto un posizionamento relativo (etichetta sopra un pulsante, icona a destra del testo, pannello in fondo allo schermo). Per i nuovi progetti, si consiglia ConstraintLayout, ma RelativeLayout è ancora ampiamente utilizzato in codice legacy e librerie.
RelativeLayout utilizza due tipi di regole: regole relative (posizionamento relativo a un altro elemento) e regole align (ancoraggio al genitore). Ogni elemento figlio può avere un numero illimitato di regole, ma le regole in conflitto (es. alignParentTop e below di un altro elemento) vengono risolte a favore dell'ultimo attributo dichiarato.
Regole relative:
- android:layout_above="@id/target" — il bordo inferiore dell'elemento è ancorato al bordo superiore di target.
- android:layout_below="@id/target" — il bordo superiore dell'elemento è ancorato al bordo inferiore di target.
- android:layout_toLeftOf="@id/target" — il bordo destro è ancorato al bordo sinistro di target.
- android:layout_toRightOf="@id/target" — il bordo sinistro è ancorato al bordo destro di target.
- android:layout_toStartOf="@id/target" — analogo a toLeftOf per le localizzazioni RTL.
- android:layout_toEndOf="@id/target" — analogo a toRightOf per RTL.
Regole align (al genitore):
- android:layout_alignParentTop="true" — il bordo superiore dell'elemento coincide con il bordo superiore del genitore.
- android:layout_alignParentBottom="true" — il bordo inferiore coincide con il bordo inferiore del genitore.
- android:layout_alignParentLeft="true" — il bordo sinistro coincide con il bordo sinistro del genitore.
- android:layout_alignParentRight="true" — il bordo destro coincide con il bordo destro del genitore.
- android:layout_alignParentStart e android:layout_alignParentEnd — per RTL.
Regole align verso altri elementi:
- android:layout_alignTop="@id/target" — la parte superiore dell'elemento coincide con la parte superiore di target.
- android:layout_alignBottom, android:layout_alignLeft, android:layout_alignRight, android:layout_alignStart, android:layout_alignEnd — analogo.
- android:layout_alignBaseline="@id/target" — allineamento per linea di base del testo (utile per stringhe con dimensioni del carattere diverse).
La centratura in RelativeLayout è impostata da tre attributi: android:layout_centerInParent="true" (centro del genitore su entrambi gli assi), android:layout_centerHorizontal="true" (centro orizzontale) e android:layout_centerVertical="true" (centro verticale). La centratura è compatibile con altre regole: un elemento può essere centrato orizzontalmente mentre è ancorato al bordo inferiore del genitore.
L'ordine Z (ordine di sovrapposizione) in RelativeLayout è determinato dall'ordine di dichiarazione degli elementi in XML. Il primo elemento dichiarato viene disegnato per primo (sarà sotto), l'ultimo — per ultimo (sarà sopra). Se è necessario modificare l'ordine di sovrapposizione senza modificare l'XML, utilizzare android:elevation (a partire da API 21) — gli elementi con elevation maggiore vengono disegnati sopra. Per le versioni precedenti all'API 21, l'ordine di sovrapposizione è controllato solo dall'ordine di dichiarazione.
Importante: RelativeLayout non supporta l'attributo android:elevation per il genitore — ogni elemento controlla la propria elevation. Quando le regole di posizionamento e l'elevation sono in conflitto (es. elementi sovrapposti), l'elevation ha priorità per il rendering, ma non per il posizionamento — un elemento con elevation maggiore può sovrapporsi visivamente a un altro, anche se le sue regole di layout lo posizionano "dietro".
Avatar centrato in alto, nome sotto l'avatar, stato sotto il nome, pulsante d'azione in fondo allo schermo. Tutti gli elementi utilizzano regole relative per l'ancoraggio sequenziale.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/avatar"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="32dp"
android:src="@drawable/avatar_placeholder" />
<TextView
android:id="@+id/user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/avatar"
android:layout_centerHorizontal="true"
android:layout_marginTop="12dp"
android:text="Ivan Ivanov"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="@+id/user_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/user_name"
android:layout_centerHorizontal="true"
android:text="Online"
android:textColor="@color/green" />
<Button
android:id="@+id/edit_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="24dp"
android:text="Modifica profilo" />
</RelativeLayout>
L'avatar è ancorato in alto tramite marginTop + centerHorizontal, il nome è sotto l'avatar tramite layout_below, lo stato sotto il nome e il pulsante è ancorato al bordo inferiore del genitore tramite alignParentBottom. Tutti gli elementi sono indipendenti tra loro — niente catene o annidamenti.
Un'icona con un badge rosso (cerchio con numero) nell'angolo in alto a destra. Il badge è posizionato rispetto all'icona tramite allineamento ai suoi bordi con margini negativi per la sovrapposizione.
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_notification" />
<TextView
android:id="@+id/badge"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignTop="@+id/icon"
android:layout_alignRight="@+id/icon"
android:layout_marginTop="-6dp"
android:layout_marginRight="-6dp"
android:gravity="center"
android:background="@drawable/badge_background"
android:text="3"
android:textColor="@android:color/white"
android:textSize="10sp" />
</RelativeLayout>
Il badge è ancorato ai bordi superiore e destro dell'icona. I margini negativi (-6dp) spostano il badge verso l'esterno, creando un effetto di sovrapposizione del bordo dell'icona. Questo è un modello popolare per le notifiche, che senza RelativeLayout richiederebbe FrameLayout o disegno personalizzato.
Modulo di login: logo centrato in alto, campo email sotto di esso, campo password sotto l'email, pulsante "Accedi" sotto la password, link "Registrati" ancorato in basso. Tutti gli elementi sono ancorati sequenzialmente tramite layout_below.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="24dp">
<TextView
android:id="@+id/logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="48dp"
android:text="MyApp"
android:textSize="32sp"
android:textStyle="bold" />
<EditText
android:id="@+id/email_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/logo"
android:layout_marginTop="32dp"
android:hint="Email" />
<EditText
android:id="@+id/password_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/email_input"
android:layout_marginTop="16dp"
android:hint="Password"
android:inputType="textPassword" />
<Button
android:id="@+id/login_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/password_input"
android:layout_marginTop="24dp"
android:text="Accedi" />
<TextView
android:id="@+id/register_link"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="16dp"
android:text="Non hai un account? Registrati"
android:textColor="@color/primary" />
</RelativeLayout>
La schermata utilizza 5 elementi a un singolo livello gerarchico. Il flusso dall'alto verso il basso (logo → email → password → pulsante) è ottenuto tramite layout_below e il link è spinto verso il basso tramite alignParentBottom. Per la stessa funzionalità, LinearLayout richiederebbe due contenitori annidati (uno per il gruppo superiore, uno per il link con weight).
Confronto di due ViewGroup per il posizionamento relativo: RelativeLayout (classico, API 1+) e ConstraintLayout (moderno, Jetpack). Criteri: flessibilità, prestazioni, supporto RTL e adattabilità.
| Caratteristica | RelativeLayout | ConstraintLayout |
|---|---|---|
| Dimensioni percentuali | No (solo fisse e match_parent) | Sì (width_percent, height_percent, guideline_percent) |
| Supporto RTL | Tramite start/end (API 17+) | Integrato |
| Chain / catene | No | Sì (spread, spread_inside, packed) |
| Barrier / Group / Flow | No | Sì (assistenti virtuali) |
| Animazioni MotionLayout | No | Sì |
| Passaggi onMeasure | 1 (senza cicli di dipendenza) | 2 (sempre, ma ottimizzati) |
| Centratura | centerInParent, centerHorizontal, centerVertical | Tramite bias (0.0–1.0) con vincoli opposti |
| Quando usare | Codice legacy, layout semplici con 3–7 elementi | Nuovi progetti, schermate complesse, layout adattivi |
RelativeLayout è inferiore a ConstraintLayout in quasi tutti gli aspetti tranne uno: è integrato in Android SDK dall'API 1 e non richiede dipendenze aggiuntive. Per i progetti che utilizzano ancora minSdk inferiore all'API 14 (Android 4.0), RelativeLayout è l'unica opzione standard per il posizionamento relativo. In tutti gli altri casi, Google raccomanda ConstraintLayout.
Domande frequenti
La ragione più probabile è la mancanza di sufficienti regole di posizionamento. Ogni elemento in RelativeLayout deve avere almeno una regola orizzontale (alignParentLeft, toRightOf, centerHorizontal) e una regola verticale (alignParentTop, below, centerVertical). Senza regole, l'elemento si trova nella posizione (0,0) e potrebbe essere nascosto sotto altri elementi o fuori dallo schermo. La seconda ragione è una dipendenza circolare (elemento A legato a B, B legato a A), che porta a un comportamento imprevedibile.
Utilizza l'attributo android:layout_centerInParent="true". Centra l'elemento su entrambi gli assi simultaneamente. Se serve solo orizzontalmente — android:layout_centerHorizontal="true", solo verticalmente — android:layout_centerVertical="true". La centratura funziona in combinazione con i margini — l'elemento verrà spostato rispetto al centro dell'offset specificato.
Sì, ma non è raccomandato. RelativeLayout esegue due passaggi onMeasure in presenza di dipendenze circolari, risultando del 15–30% più lento di ConstraintLayout nelle liste RecyclerView. Per i layout degli elementi di RecyclerView, usa ConstraintLayout — fornisce una gerarchia piatta con tempi di misurazione minimi. Se RelativeLayout è già utilizzato in un progetto legacy, assicurati che gli elementi non creino dipendenze circolari e misura gli FPS di scorrimento tramite Profile GPU Rendering.
android:layout_margin imposta i margini su tutti i lati contemporaneamente. android:layout_marginTop — solo in alto. L'attributo più specifico ha priorità: se sono impostati sia layout_margin (16dp) che layout_marginTop (8dp), il margine superiore sarà 8dp. In RelativeLayout, il margine funziona rispetto al vincolo, non rispetto all'elemento adiacente: layout_marginTop con layout_below="@id/target" è il margine dal bordo superiore dell'elemento al bordo inferiore di target.
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