FrameLayout: concetti chiave, posizionamento semplice in Android

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

Scopri i concetti chiave di FrameLayout — la ViewGroup più semplice nell'SDK Android, progettata per ospitare un singolo elemento figlio (di solito) o sovrapporre più elementi uno sull'altro. FrameLayout è utile per contenitori segnaposto, frammenti, indicatori di caricamento ed elementi in primo piano. Non gestisce il posizionamento dei figli — ogni elemento successivo viene disegnato sopra il precedente e la loro posizione è determinata da layout_gravity (left, top, right, bottom, center). Gli scenari di base sono descritti nel Riferimento API FrameLayout.

Punti chiave

  • Sovrapposizione di livelli — FrameLayout posiziona gli elementi sequenzialmente uno sopra l'altro; l'ultimo dichiarato in XML viene disegnato più in alto.
  • Primo piano — l'attributo android:foreground consente di sovrapporre un drawable sopra tutti gli elementi figli, utile per effetti e mascheramento.
  • measureAllChildren — per impostazione predefinita, FrameLayout misura tutti i figli, anche quelli invisibili (GONE). Disabilitarlo accelera il disegno del 20–60%.
  • layout_gravity — l'unico modo per posizionare un elemento figlio all'interno di FrameLayout: top, bottom, left, right, center.
  • Utilizzo con Fragment — FrameLayout è il contenitore standard per FragmentTransaction.replace(), sostituendo il contenuto senza ricreare l'attività.

Cos'è FrameLayout?

FrameLayout è la ViewGroup più semplice nell'SDK Android, progettata per bloccare un'area dello schermo e visualizzare una singola vista figlia (o sovrapporne diverse). A differenza di LinearLayout (disposizione sequenziale) e RelativeLayout (posizionamento relativo), FrameLayout non modifica le posizioni dei figli — ogni nuovo figlio viene posizionato nell'angolo superiore sinistro (0,0) per impostazione predefinita e disegnato sopra il precedente.

FrameLayout è stato introdotto nell'API Level 1 e rimane il contenitore Android più leggero: non sovrascrive onMeasure con logica complessa ed esegue un numero minimo di operazioni di layout. Secondo Android Performance Blog, FrameLayout esegue onLayout in un unico passaggio e non aggiunge praticamente alcun overhead rispetto al posizionamento diretto di una View. Questo lo rende una scelta ideale per i contenitori dove la velocità è importante: layout di elementi RecyclerView (in combinazione con ConstraintLayout per il posizionamento), contenitori di Fragment, livelli di sovrapposizione.

La dimensione di FrameLayout per impostazione predefinita è determinata dall'elemento figlio più grande (se match_parent non è impostato). Se non viene specificato alcun figlio, FrameLayout si riduce a (0,0). L'attributo android:measureAllChildren (sezione sottostante) modifica questo comportamento.

FrameLayout nella gerarchia ViewGroup di Android

FrameLayout eredita da ViewGroup ed è il genitore diretto di molti contenitori specializzati: FragmentContainerView (frammenti), CardView (schede con ombra), ScrollView (figlio singolo), NestedScrollView. Quando si crea un'Activity con navigazione tramite Fragment, il modello standard di Android Studio utilizza FrameLayout (o FragmentContainerView) come contenitore radice per i frammenti.

Primo piano e measureAllChildren

android:foreground — un attributo di FrameLayout che specifica un drawable disegnato sopra tutti gli elementi figli. A differenza di background (sotto i figli), foreground viene visualizzato sopra il contenuto e può essere trasparente. Viene utilizzato per: effetti di sovrapposizione al tocco (ripple tramite ?attr/selectableItemBackground), mascheramento di immagini, visualizzazione di indicatori di stato (segno di spunta su un'immagine).

Foreground supporta le risorse drawable standard: ColorDrawable, ShapeDrawable, RippleDrawable, LayerDrawable. Dall'API 23+, android:foregroundGravity è disponibile per il posizionamento del primo piano (fill, center, top, bottom). In modalità fill, foreground si estende su tutto FrameLayout; in modalità center, viene disegnato al centro.

android:measureAllChildren — un attributo booleano (true per impostazione predefinita) che determina se misurare tutti gli elementi figli quando si calcola la dimensione di FrameLayout. Se true (predefinito), FrameLayout considera le dimensioni di tutti i figli, inclusi GONE (con dimensione 0). Se false, FrameLayout misura solo i figli VISIBLE e INVISIBLE — gli elementi GONE vengono esclusi dal calcolo. Secondo Google I/O 2019, disabilitare measureAllChildren per contenitori con molti elementi GONE (ad esempio, elenchi con visibilità alternata) accelera il disegno iniziale del 20–60%.

layout_gravity: Posizionamento all'interno di FrameLayout

android:layout_gravity — un attributo di un elemento figlio di FrameLayout (e di altri ViewGroup) che definisce la sua posizione all'interno del contenitore. In FrameLayout, layout_gravity è l'unico modo per controllare la posizione di un elemento figlio, poiché FrameLayout non fornisce proprie regole di posizionamento (come RelativeLayout) o direzione (come LinearLayout).

Valori possibili: top, bottom, left, right, center, center_horizontal, center_vertical, fill, fill_horizontal, fill_vertical, clip_horizontal, clip_vertical. Combinati tramite |: android:layout_gravity="bottom|center_horizontal" — l'elemento è fissato al bordo inferiore e centrato orizzontalmente. Per elementi più piccoli di FrameLayout, layout_gravity determina la loro posizione nello spazio libero.

Se layout_gravity non è impostato, l'elemento viene posizionato nell'angolo superiore sinistro (top|left) per impostazione predefinita. Per un FrameLayout contenente più figli, ciascuno può avere il proprio layout_gravity — un elemento può essere nell'angolo superiore sinistro, un altro nell'angolo inferiore destro, un terzo centrato. Ciò consente di creare semplici sovrapposizioni (ad esempio, un'icona di chiusura su un'immagine).

Differenza: gravity vs layout_gravity

android:gravity (attributo genitore) allinea il contenuto all'interno di FrameLayout — ad esempio, il testo all'interno di un TextView. android:layout_gravity (attributo figlio) allinea l'elemento stesso all'interno di FrameLayout. Nel contesto di FrameLayout, gravity definisce come i figli vengono posizionati per impostazione predefinita (simile a layout_gravity per tutti i figli contemporaneamente), ma il layout_gravity di ogni singolo elemento sovrascrive il valore genitore.

Esempi: XML e casi d'uso

Esempio 1: Sovrapposizione di base — Etichetta su immagine

Un'immagine con un'etichetta di testo nell'angolo inferiore destro. FrameLayout contiene un ImageView che riempie lo schermo e un TextView con layout_gravity="bottom|end" per il posizionamento sull'immagine.

xml
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="200dp">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/product_photo"
        android:scaleType="centerCrop" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="8dp"
        android:background="@drawable/badge_background"
        android:elevation="2dp"
        android:paddingHorizontal="8dp"
        android:paddingVertical="4dp"
        android:text="-30%"
        android:textColor="@android:color/white"
        android:textSize="14sp"
        android:textStyle="bold" />

</FrameLayout>

ImageView riempie l'intero FrameLayout (altezza 200dp). Il TextView con layout_gravity="bottom|end" viene posizionato nell'angolo inferiore destro sopra l'immagine. elevation=2dp aggiunge un'ombra sotto l'etichetta, separandola visivamente dall'immagine. Questo esempio minimo avrebbe richiesto un contenitore annidato o codice personalizzato in LinearLayout.

Esempio 2: Indicatore di caricamento (barra di progresso sul contenuto)

Uno schermo con contenuto e una barra di progresso centrata che appare durante il caricamento. FrameLayout contiene due elementi: il contenuto e un ProgressBar con visibility="gone" (alternato nel codice).

xml
<FrameLayout
    android:id="@+id/content_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/content_text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Contenuto caricato"
        android:textSize="18sp" />

    <ProgressBar
        android:id="@+id/loading_spinner"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_gravity="center"
        android:visibility="gone" />

</FrameLayout>

La ProgressBar è nascosta per impostazione predefinita (gone). All'avvio del caricamento, viene chiamato findViewById(R.id.loading_spinner).visibility = View.VISIBLE — lo spinner appare centrato sopra il contenuto. Dopo il caricamento — .visibility = View.GONE. FrameLayout fornisce sovrapposizione senza spostare la posizione del contenuto — il testo non si sposta quando appare lo spinner, poiché la ProgressBar viene disegnata sopra.

Esempio 3: Contenitore di Fragment

FrameLayout come contenitore standard per FragmentTransaction. L'attività sostituisce i frammenti all'interno di questo contenitore in base alla navigazione.

xml
<FrameLayout
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
kotlin
import androidx.fragment.app.FragmentTransaction

val fragmentContainer = R.id.fragment_container

fun navigateTo(fragment: Fragment) {
    supportFragmentManager
        .beginTransaction()
        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
        .replace(fragmentContainer, fragment)
        .addToBackStack(null)
        .commit()
}

FrameLayout come contenitore di frammenti è il modo più leggero per supportare la navigazione tramite Fragment. FragmentContainerView (una sottoclasse di FrameLayout) è raccomandato con Navigation Component 2.4+, ma un semplice FrameLayout rimane valido per FragmentTransaction manuali. Il vantaggio principale è che FragmentTransaction.replace() sostituisce completamente il contenuto senza influenzare l'Activity.

Quando usare FrameLayout

FrameLayout è ottimale per quattro scenari: contenitore di frammenti (FragmentContainerView o FrameLayout), sovrapposizione di caricamento (ProgressBar sul contenuto), etichette su schede (etichetta su immagine), contenitore segnaposto per ViewStub (caricamento lazy).

Non adatto per: posizionamento complesso di più elementi (usa ConstraintLayout), elenchi sequenziali (LinearLayout o RecyclerView), layout dinamici con modifica dell'ordine degli elementi.

FrameLayout come elemento radice dello schermo — cattiva pratica se lo schermo contiene più di 2–3 elementi. Per un contenitore radice, usa ConstraintLayout — offre più controllo sul posizionamento senza perdita di prestazioni. Usa FrameLayout solo per blocchi figli dove è necessaria sovrapposizione o segnaposto.

Domande frequenti

Qual è la differenza tra FrameLayout e ConstraintLayout?

FrameLayout — un contenitore minimalista senza sistema di posizionamento (solo layout_gravity), progettato per la sovrapposizione di elementi. ConstraintLayout — un sistema di layout completo con constraint, catene, barriere, dimensioni percentuali e supporto di MotionLayout. FrameLayout è più veloce per casi semplici (1 figlio o sovrapposizione); ConstraintLayout è necessario per layout complessi. Scelta: FrameLayout per sovrapposizione di caricamento e contenitore di frammenti; ConstraintLayout per tutto il resto.

Come fare in modo che FrameLayout occupi solo lo spazio del figlio più grande?

Imposta la dimensione di FrameLayout su wrap_content sull'asse desiderato (android:layout_width="wrap_content" e/o android:layout_height="wrap_content"). FrameLayout si adatterà quindi alla dimensione dell'elemento figlio più grande. Se tutti i figli sono più piccoli di FrameLayout, lo spazio in eccesso rimane vuoto. Per un controllo preciso, usa match_parent con padding fisso.

Perché gli elementi in FrameLayout si sovrappongono tra loro?

Questo è il comportamento previsto di FrameLayout — non distribuisce i figli nello spazio ma li disegna sequenzialmente uno sopra l'altro. Se vuoi che gli elementi non si sovrappongano, usa un altro contenitore (LinearLayout, ConstraintLayout). Per sovrapposizione parziale con controllo dell'ordine di disegno, usa layout_gravity per l'offset ed elevation per l'ordine Z.

Qual è più veloce: FrameLayout o ConstraintLayout?

FrameLayout è più veloce per i casi più semplici — un elemento figlio, senza posizionamento complesso. FrameLayout esegue onMeasure in un tempo minimo senza calcolare constraint. Tuttavia, la differenza è evidente solo a centinaia di ripetizioni (RecyclerView con decine di migliaia di elementi). Per uno schermo tipico (1–3 FrameLayout), la differenza è in microsecondi e non influisce sull'UX. ConstraintLayout è la scelta universale per il 95% delle attività.

Riepilogo

  • FrameLayout — la ViewGroup Android più semplice per sovrapposizione di elementi e contenitori segnaposto con overhead minimo.
  • Sovrapposizione di livelli — ogni nuovo figlio viene disegnato sopra il precedente; l'ultimo dichiarato in XML è il più in alto.
  • Primo piano — un drawable sopra tutti i figli per effetti di sovrapposizione, mascheramento e animazioni ripple.
  • measureAllChildren — disabilitare (false) esclude gli elementi GONE dal calcolo delle dimensioni, accelerando il disegno del 20–60%.
  • layout_gravity — l'unico meccanismo di posizionamento: top, bottom, left, right, center e le loro combinazioni.
  • Contenitore di Fragment — il caso d'uso più comune: FrameLayout (o FragmentContainerView) per FragmentTransaction.replace().
  • Prestazioni — il contenitore più veloce per 1 figlio; per layout complessi, è inferiore a ConstraintLayout.

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