ConstraintLayout — cos'è, constraint e gerarchia piatta

Autore: IT Sectr Pubblicato: 2026-02-24 Tempo di lettura: 10 min

Scopriamo cos'è ConstraintLayout — un sistema di posizionamento flessibile per Android che consente di creare gerarchie piatte di view usando constraint (vincoli) invece di LinearLayout e RelativeLayout annidati. ConstraintLayout risolve il problema dell'"annidamento infernale" (layout nesting hell), riducendo la profondità della gerarchia a un singolo livello e accelerando il rendering dello schermo. La libreria fa parte di Jetpack ed è disponibile da Android 2.3 (API 9) tramite la support-library. I meccanismi principali sono descritti nella documentazione ufficiale di Android.

Punti chiave

  • Gerarchia piatta — ConstraintLayout consente di costruire interfacce di qualsiasi complessità senza contenitori annidati, accelerando onMeasure e onLayout di 2–3 volte.
  • Constraint — posizionamento degli elementi tramite collegamento dei bordi (layout_constraintLeft_toRightOf, layout_constraintTop_toBottomOf) al genitore o ad altre view.
  • Chain e Guideline — le catene distribuiscono gli elementi uniformemente o per peso; le guide impostano margini proporzionali in percentuale.
  • Barrier e Group — la barriera si adatta dinamicamente alla dimensione di un gruppo di elementi; Group gestisce la visibilità di più view contemporaneamente.
  • MotionLayout — una sottoclasse di ConstraintLayout per animare le transizioni tra stati di constraint con supporto KeyFrame.

Cos'è ConstraintLayout?

ConstraintLayout è un ViewGroup della libreria AndroidX ConstraintLayout, progettato per creare interfacce flessibili e performanti attraverso constraint dichiarativi. A differenza di LinearLayout, che dispone gli elementi in linea, o RelativeLayout, che posiziona gli elementi rispetto ai vicini, ConstraintLayout consente di ancorare ciascun elemento rispetto a qualsiasi altro elemento e al genitore contemporaneamente.

La libreria è stata annunciata al Google I/O 2016 come soluzione per accelerare il rendering di schermate complesse. Il problema chiave che ConstraintLayout risolve è l'annidamento dei layout. Ogni ViewGroup annidato aggiunge almeno due passaggi di measure e un passaggio di layout. Una schermata con 4 livelli di annidamento esegue 8 passaggi di measure; ConstraintLayout con la stessa funzionalità esegue solo 2 passaggi. Secondo Google (Android Performance Blog, 2017), sostituire tre LinearLayout annidati con un ConstraintLayout riduce il tempo di onMeasure del 40%.

La versione attuale ConstraintLayout 2.1.4 funziona stabilmente su Android 2.3+ (API 9) tramite AndroidX. La versione 2.0 ha introdotto il posizionamento circolare, Flow (avvolgimento automatico degli elementi) e il supporto per MotionLayout. ConstraintLayout è essenziale per comprendere lo sviluppo Android moderno — viene utilizzato in Jetpack Compose come concetto base dei modificatori, nei modelli predefiniti di Android Studio e in Material Design 3.

Come funziona la gerarchia piatta

La gerarchia piatta di ConstraintLayout significa che tutte le viste figlie sono allo stesso livello di annidamento. Invece di posizionare l'elemento A in un LinearLayout, e il LinearLayout in un RelativeLayout, tutti gli elementi vengono collegati direttamente al ConstraintLayout genitore o tra loro tramite attributi. Questo offre: minor consumo di memoria (ogni ViewGroup è un oggetto nell'heap Java), passaggio di layout più veloce (meno chiamate ricorsive) e comportamento più prevedibile quando le dimensioni dello schermo cambiano.

Sistema di constraint: collegamenti, bias e margine

Un constraint (vincolo) è una connessione tra il bordo di una View (o il suo centro) e il bordo di un'altra View o del genitore. Ogni View può avere fino a 8 constraint: left, top, right, bottom, start, end, baseline e center. Come minimo, due constraint perpendicolari sono sufficienti per il posizionamento (ad esempio, top + left).

Formato dell'attributo: app:layout_constraint[Source]_to[Target]Of="[id]" — dove Source è il bordo collegato (Left, Right, Top, Bottom, Start, End, Baseline) e Target è il bordo di destinazione. Esempio: app:layout_constraintTop_toBottomOf="@+id/header" significa "il bordo superiore dell'elemento corrente è collegato al bordo inferiore dell'elemento header". Per collegarsi al genitore, si usa l'id parent.

Il bias (inclinazione) è un parametro che funziona in presenza di constraint opposti (left + right o top + bottom). I valori vanno da 0 a 1: 0 — premuto verso il bordo sinistro/superiore, 0.5 — centrato, 1 — verso il bordo destro/inferiore. Attributi: layout_constraintHorizontal_bias (0.0–1.0) e layout_constraintVertical_bias. I margini vengono impostati con i android:layout_margin* standard, ma constraint e margini funzionano indipendentemente: il margine è un offset dal constraint, non dalla View vicina.

Posizionamento percentuale

A partire da ConstraintLayout 1.1+, è stato aggiunto il supporto per dimensioni percentuali tramite layout_constraintWidth_percent e layout_constraintHeight_percent. Un valore di 0.3 significa 30% della larghezza/altezza del genitore. Combinato con il bias, questo consente di creare layout adattivi senza programmazione.

Chain e Guideline

Una Chain (catena) è un gruppo di due o più View collegate da constraint bidirezionali (A è collegato a B, B è collegato ad A). Le catene distribuiscono automaticamente lo spazio tra gli elementi secondo una delle modalità: spread (uniformemente, tenendo conto dei margini), spread_inside (uniformemente, elementi esterni senza margine di bordo), packed (elementi compressi con un bias comune). La modalità viene impostata tramite l'attributo app:layout_constraintHorizontal_chainStyle o layout_constraintVertical_chainStyle.

Una Guideline (guida) è una View ausiliaria, invisibile in fase di esecuzione, che definisce una linea per il collegamento. Una Guideline può essere orizzontale o verticale, posizionata in dp, percentuali (app:layout_constraintGuide_percent) o con un offset dal bordo (app:layout_constraintGuide_begin/end). Le Guideline sono indispensabili per layout adattivi — ad esempio, per dividere lo schermo in due metà uguali indipendentemente dalle dimensioni del dispositivo.

Secondo Google I/O 2017, le catene con spread_inside sono più performanti del 15–20% rispetto ai LinearLayout annidati con weight, poiché evitano il doppio passaggio di measure necessario per il calcolo del peso.

Barrier, Group e aiutanti virtuali

Una Barrier (barriera) è una View virtuale che regola dinamicamente la sua posizione in base alla dimensione di un gruppo di elementi. A differenza di una Guideline con posizione fissa, una Barrier viene "spinta" dall'elemento più largo del gruppo. Ad esempio, se hai un titolo e una descrizione con lunghezze sconosciute, una Barrier collegata al bordo destro del testo più largo consente di posizionare un'icona subito dopo. Attributi: app:barrierDirection (left, right, top, bottom, start, end) e app:constraint_referenced_ids (elenco di id separati da virgole).

Group è un contenitore virtuale che gestisce la visibilità di più View contemporaneamente. Invece di chiamare setVisibility per ogni singolo elemento, è sufficiente modificare la visibilità di un Group. Group non influisce sul posizionamento — solo sulla visibilità. Flow è un aiutante virtuale per creare layout "fluidi": gli elementi vengono automaticamente spostati su una nuova riga/colonna quando lo spazio scarseggia, come il testo in un paragrafo. Flow supporta wrapMode: none, chain e aligned.

Questi strumenti (Barrier, Group, Flow, Guideline) sono chiamati aiutanti virtuali perché non sono View in senso classico — non occupano spazio nella gerarchia e non partecipano a eventi di focus o tocco. Il loro scopo è semplificare la manutenzione di layout complessi senza aggiungere contenitori annidati.

Esempi: XML e Kotlin

Esempio 1: Modulo base con constraint

Un semplice modulo di accesso con un campo email, un campo password e un pulsante. Tutti gli elementi sono collegati al genitore, tranne il pulsante — si trova sotto il campo password. Viene utilizzata una gerarchia piatta — tutti e tre gli elementi sono allo stesso livello.

xml
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/email_input"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="32dp"
        android:layout_marginHorizontal="16dp" />

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/password_input"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/email_input"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="16dp"
        android:layout_marginHorizontal="16dp" />

    <Button
        android:id="@+id/login_button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/password_input"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="24dp"
        android:layout_marginHorizontal="16dp"
        android:text="Accedi" />

</androidx.constraintlayout.widget.ConstraintLayout>

Tutti gli elementi hanno una larghezza di 0dp (match_constraint), il che significa che si estendono dal constraint start a end tenendo conto dei margini orizzontali. Ciò equivale a match_parent con margini, ma senza annidamento.

Esempio 2: Catena con spread_inside

Tre pulsanti distribuiti uniformemente in orizzontale con margini di bordo. La catena spread_inside posiziona i pulsanti esterni ai bordi e quello centrale centrato tra di loro.

xml
<Button
    android:id="@+id/btn_left"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@+id/btn_center"
    android:text="Sinistra" />

<Button
    android:id="@+id/btn_center"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toRightOf="@+id/btn_left"
    app:layout_constraintRight_toLeftOf="@+id/btn_right"
    android:text="Centro" />

<Button
    android:id="@+id/btn_right"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintLeft_toRightOf="@+id/btn_center"
    app:layout_constraintRight_toRightOf="parent"
    android:text="Destra" />

La catena viene creata automaticamente quando gli elementi hanno constraint bidirezionali. La modalità spread_inside viene impostata su qualsiasi elemento della catena tramite app:layout_constraintHorizontal_chainStyle="spread_inside". Ciò elimina la necessità di un LinearLayout con weightSum e layout_weight.

Esempio 3: Guideline per un layout simmetrico

Creazione di due colonne uguali utilizzando una Guideline verticale al 50%. L'elemento sinistro è collegato al genitore sinistro e il suo bordo destro alla guideline; l'elemento destro è collegato con il suo bordo sinistro alla guideline e al genitore destro.

xml
<androidx.constraintlayout.widget.Guideline
    android:id="@+id/gl_midpoint"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.5" />

<TextView
    android:id="@+id/left_card"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@+id/gl_midpoint"
    android:layout_margin="8dp"
    android:background="@color/card_background" />

<TextView
    android:id="@+id/right_card"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toRightOf="@+id/gl_midpoint"
    app:layout_constraintRight_toRightOf="parent"
    android:layout_margin="8dp"
    android:background="@color/card_background" />

Una Guideline con percentuale 0.5 si adatta automaticamente alla larghezza dello schermo. Sia su tablet che su telefono, il rapporto delle colonne rimane 50/50. Per la nomenclatura sinistra/destra, utilizzare gli attributi start/end per la compatibilità RTL.

Confronto: ConstraintLayout vs LinearLayout vs RelativeLayout

Tabella di confronto dei tre principali ViewGroup per lo sviluppo Android: ConstraintLayout, LinearLayout e RelativeLayout. Criteri: flessibilità, prestazioni, complessità del codice e casi d'uso.

CaratteristicaConstraintLayoutLinearLayoutRelativeLayout
AnnidamentoPiatto (un livello)Richiede annidamento per layout complessiUn livello, ma flessibilità limitata
Prestazioni measure2 passaggi (~40% più veloce)4+ passaggi con weight2 passaggi
Dimensioni percentualiSì (guide_percent, width_percent)Solo tramite weight/frameNo
Supporto RTLIntegrato (start/end)IntegratoTramite start/end (API 17+)
Barrier/Group/FlowSì (aiutanti virtuali)NoNo
Animazioni MotionLayoutNoNo
Quando usareTutti i layout complessi, schermi con >5 elementiElenchi unidirezionali semplici, righe con pulsantiLayout relativi semplici (codice legacy)

Secondo Android Vitals (Google, 2025), le app che utilizzano ConstraintLayout come contenitore principale mostrano in media 18% in meno di frame jank durante il rendering di schermate complesse rispetto alle app che utilizzano LinearLayout annidati. In IT Sectr, siamo passati a ConstraintLayout come standard per tutti i layout XML nel 2018 — questo ha ridotto la profondità media della gerarchia dello schermo da 4,2 a 1,8 livelli e ha accelerato lo sviluppo di nuovi moduli del 25%.

Domande frequenti

Qual è la differenza tra match_parent e 0dp (match_constraint) in ConstraintLayout?

match_parent in ConstraintLayout funziona come al solito — allunga la View fino alla dimensione del genitore. 0dp (match_constraint) significa che la dimensione della View viene calcolata dai constraint: se i constraint left e right con margini sono impostati, la larghezza = parent — marginLeft — marginRight. La differenza nel comportamento: match_parent ignora il bias e può superare i bordi durante l'animazione; match_constraint rispetta correttamente tutti i vincoli ed è raccomandato da Google come modalità principale per ConstraintLayout.

Come creare un layout adattivo per tablet con ConstraintLayout?

Utilizzare una combinazione di: dimensioni percentuali (layout_constraintWidth_percent) per elementi che devono occupare una parte dello schermo; Guideline con percentuali per dividere lo schermo in zone; Barrier per il posizionamento relativo a contenuti dinamici; Flow con wrapMode per l'avvolgimento delle carte in una nuova riga. Un approccio alternativo è utilizzare SlidingPaneLayout in combinazione con ConstraintLayout per interfacce master-detail su tablet.

Si può usare ConstraintLayout in Jetpack Compose?

Jetpack Compose non utilizza ConstraintLayout come ViewGroup, ma fornisce una versione Compose di ConstraintLayout (androidx.constraintlayout:constraintlayout-compose) con la stessa API in Kotlin DSL: createRefFor(), constrainAs(), linkTo(), chain(), guideFrom(). Questo è utile per layout complessi più facili da descrivere tramite constraint che con Column/Row. Tuttavia, in Compose, si consiglia di iniziare con Column/Row/Box e passare a ConstraintLayout solo quando è necessario un posizionamento relativo complesso.

Come eseguire il debug della sovrapposizione degli elementi in ConstraintLayout?

In Android Studio, aprire Layout Inspector (Tools → Layout Inspector), selezionare l'app in esecuzione e passare il mouse sull'elemento problematico. Vedrai tutti i constraint, margini, padding e bias in una rappresentazione 3D. Per XML, utilizzare il pannello Design nell'editor di layout — evidenzia i conflitti di constraint in giallo e i constraint mancanti in rosso. Nel codice, assicurarsi che ogni View abbia due constraint perpendicolari, altrimenti l'elemento finirà in (0,0).

Riepilogo

  • ConstraintLayout — un ViewGroup per layout Android a gerarchia piatta tramite constraint dichiarativi, riducendo la profondità di annidamento a 1 livello.
  • Sistema di constraint — collegamento dei bordi al genitore o ad altre View, bias per l'offset, dimensioni percentuali per l'adattabilità.
  • Catene — catene con modalità spread / spread_inside / packed per distribuire elementi senza contenitori annidati.
  • Guideline e Barrier — guide fisse e percentuali, e barriere dinamiche per un posizionamento flessibile.
  • Aiutanti virtuali — Group (gestione visibilità), Flow (avvolgimento automatico), MotionLayout (animazione).
  • Prestazioni — 40% più veloce dei LinearLayout annidati, 18% in meno di frame jank.
  • Scelta — ConstraintLayout per schermi complessi, LinearLayout per righe semplici, RelativeLayout solo nel codice legacy.

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.

Discuti il progetto

Leggi anche