Modifier — catena di modificatori e prestazioni in Compose

Autore: IT Sectr Pubblicato: 2026-06-28 Tempo di lettura: 8 min

Modifier è un oggetto immutabile in Jetpack Compose che definisce le proprietà di un componente UI: dimensione, padding, sfondo, gestione dei gesti e comportamento. I modificatori vengono combinati in una catena attraverso chiamate sequenziali e l'ordine della loro applicazione influisce criticamente sul risultato. Secondo Google Android Developers, 2026, l'uso corretto di Modifier è la base per costruire interfacce flessibili e performanti in UI dichiarativa.

Punti chiave

  • Modifier è un oggetto immutabile che descrive aspetto e comportamento di un componente UI
  • Catena di modificatori costruita sequenzialmente, l'ordine influisce sulla visualizzazione
  • L'ordine conta: padding → size differisce da size → padding
  • Modifier.composed permette di creare modificatori compositi personalizzati
  • Ottimizzazione: evita di ricreare Modifier ad ogni ricomposizione

Cosa sono i Modifier in Jetpack Compose

Modifier è un'interfaccia del pacchetto androidx.compose.ui che implementa il pattern Composite. Ogni modificatore è un elemento di catena che avvolge il precedente e aggiunge il proprio comportamento. Modifier è immutabile — qualsiasi modifica crea un nuovo oggetto tramite copia con un nuovo elemento aggiunto alla catena. Ciò consente di condividere in sicurezza un singolo Modifier tra più componenti.

Le funzioni di modificatore di base vengono chiamate tramite l'oggetto compagno Modifier (ad esempio, Modifier.padding(), Modifier.fillMaxWidth()). Ogni funzione restituisce un nuovo Modifier con l'elemento aggiunto. Se ci sono più modificatori, vengono combinati in una catena: Modifier.padding(16.dp).fillMaxWidth().background(Color.Blue). L'ordine va dall'esterno verso l'interno rispetto all'elemento UI.

A differenza delle View tradizionali dove le proprietà venivano impostate tramite setter (view.setPadding(...), view.setBackground(...)), in Compose Modifier è una descrizione dichiarativa. Il componente non "applica" i modificatori in fase di esecuzione — LayoutNode percorre la catena Modifier durante la composizione e costruisce un elenco di Modifier.Element che vengono poi elaborati durante le fasi di misurazione e layout.

Catena di modificatori e ordine di applicazione

L'ordine dei modificatori è uno degli errori più comuni in Compose. Ogni modificatore avvolge il precedente e le operazioni vengono applicate dall'esterno verso l'interno. Ad esempio, padding(16.dp).clickable { }: prima viene aggiunto il padding attorno all'elemento, poi l'area di clic include il padding. clickable { }.padding(16.dp): l'area di clic è uguale alla dimensione dell'elemento prima, poi il padding viene aggiunto attorno — cliccare sul padding non funzionerà.

Regola mnemonica: leggi la catena da sinistra a destra e applica dall'esterno verso l'interno. Il primo modificatore è il più esterno, applicato all'area attorno all'elemento. L'ultimo è il più interno, applicato direttamente al contenuto. I modificatori di dimensione (size, fillMaxWidth) dovrebbero venire dopo il padding se il padding è necessario dal genitore, o prima del padding se il contenuto deve prima essere vincolato e poi centrato.

Esempio: size(100.dp).padding(10.dp) — elemento di dimensione fissa 100dp, poi padding di 10dp all'esterno (dimensione finale 120dp). padding(10.dp).size(100.dp) — il padding di 10dp riduce lo spazio disponibile a (genitore - 20dp), poi size(100dp) può superare il genitore. Pensa sempre deliberatamente all'ordine, utilizzando test di visualizzazione per verificare il risultato.

OrdineRisultato
padding → clickableIl clic funziona anche sull'area di padding
clickable → paddingIl clic funziona solo sul contenuto, il padding è zona morta
size → paddingElemento size(100), padding esterno → 100+2*pad
padding → sizeIl padding riduce lo spazio, size può superare i limiti
background → paddingLo sfondo riempie l'intero elemento inclusa l'area esterna
padding → backgroundLo sfondo solo all'interno del padding (area esterna trasparente)

Tipi di modificatori: dimensione, padding, decorazione e comportamento

La libreria standard di Compose include ~50+ modificatori suddivisi in categorie. Dimensione e posizionamento: Modifier.size(), width(), height(), fillMaxSize(), fillMaxWidth(), fillMaxHeight(), defaultMinSize(), requiredSize(). Padding e bordi: padding(), offset(), margin (impostato tramite padding del genitore o Layout). Decorazione: background(), border(), clip(), alpha(), shadow(), blur().

Comportamento e gesti: clickable(), combinedClickable(), pointerInput(), draggable(), swipeable(). Disposizione nel contenitore: weight() (per Row/Column), align(), alignBy(), matchParentSize(). Semantica e accessibilità: semantics(), testTag(), clearAndSetSemantics(). Disegno: drawBehind(), drawWithContent(), drawModifier() — modificatori che consentono il disegno personalizzato sulla tela.

I modificatori semantici sono una categoria speciale. Modifier.semantics {} definisce come l'elemento sarà rappresentato nell'albero di Accessibilità. Compose popola automaticamente la semantica dal testo, ma i componenti personalizzati necessitano di ruoli, stati e azioni impostati manualmente. Questo è fondamentale per la conformità WCAG 2.2 e il corretto funzionamento di TalkBack (Android) e VoiceOver (iOS).

kotlin
@Composable
fun ModifierDemo() {
    // Catena di modificatori con ordine corretto
    Box(
        modifier = Modifier
            .size(150.dp)
            .padding(8.dp)
            .border(2.dp, Color.Gray)
            .background(Color(0xFFE3F2FD))
            .clickable { /* handle click */ }
            .semantics {
                contentDescription = "Demo card with click action"
                role = Role.Button
            }
    ) {
        Text("Toccami")
    }
}

Creazione di modificatori personalizzati con Modifier.composed

Modifier.composed è un metodo factory che consente di creare modificatori compositi in grado di utilizzare altri modificatori, LocalComposition e stato locale. A differenza di una normale funzione di estensione, composed crea un'istanza ogni volta che viene applicato, consentendo al modificatore di avere un proprio stato.

Quando usare composed: combinazioni ricorrenti di modificatori (ad esempio, stile scheda standard: padding + background + border + clickable); modificatori con stato (cambio di sfondo animato alla pressione); accesso a CompositionLocals (schema colori MaterialTheme, densità pixel). Per i casi ordinari, una normale funzione di estensione senza composed è sufficiente.

Prestazioni di composed: ogni chiamata crea un nuovo oggetto modificatore, che può portare ad allocazioni extra durante la ricomposizione. Per evitarlo, avvolgi composed in remember. Google raccomanda di usare composed solo quando effettivamente serve stato o CompositionLocal all'interno. Per combinazioni statiche, usa normali funzioni di estensione.

kotlin
// Modificatore personalizzato tramite composed con stato
fun Modifier.cardStyle(
    elevation: Dp = 4.dp,
    isSelected: Boolean = false
): Modifier = this.composed {
    val backgroundColor = if (isSelected)
        MaterialTheme.colorScheme.primaryContainer
    else
        MaterialTheme.colorScheme.surface

    this
        .fillMaxWidth()
        .padding(12.dp)
        .background(backgroundColor, RoundedCornerShape(8.dp))
        .shadow(elevation, RoundedCornerShape(8.dp))
}

// Esempio di utilizzo
@Composable
fun CardList() {
    Column {
        Box(Modifier.cardStyle()) { Text("Elemento 1") }
        Box(Modifier.cardStyle(isSelected = true)) { Text("Selezionato") }
    }
}

// Versione statica (senza composed) — più veloce
fun Modifier.simpleCardStyle(): Modifier =
    this.fillMaxWidth().padding(8.dp).clip(RoundedCornerShape(4.dp))

Prestazioni di Modifier e migliori pratiche

Evita di ricreare Modifier ad ogni ricomposizione. Se il modificatore non dipende da dati mutabili — spostalo in una costante o remember. Ogni chiamata a Modifier.padding().background() crea nuovi oggetti Modifier.Element. In un componente isolato è trascurabile, ma in un LazyColumn con centinaia di elementi, le allocazioni extra causano un notevole rallentamento durante lo scorrimento.

Regola: se la catena di modificatori non dipende dai parametri della funzione Composable — dichiarala come val fuori dalla funzione (a livello di file o Companion). Se dipende — usa remember(dipendenza) { ... }. Per i modificatori che sono sempre uguali, val fuori dal Composable è più efficiente: tali oggetti vengono creati una volta per l'intera durata dell'applicazione.

Migliori pratiche per l'ordine di Modifier: posiziona i modificatori in ordine logico: prima dimensione/padding (layout), poi decorazione (background, border), poi comportamento (clickable, pointerInput). Questo non solo migliora la leggibilità ma aiuta anche Compose Runtime a ottimizzare la catena durante la misurazione. Evita anche elementi Box annidati eccessivi con diversi Modifier — spesso un singolo Modifier sul contenitore genitore può sostituire 2-3 annidati.

kotlin
// ✅ Buono: costante fuori dal Composable
private val cardModifier = Modifier
    .fillMaxWidth()
    .padding(16.dp)
    .clip(RoundedCornerShape(8.dp))

@Composable
fun CardContent() {
    Box(cardModifier.background(Color.White)) { ... }
}

// ❌ Cattivo: ricreazione ad ogni ricomposizione
@Composable
fun BadCard() {
    Box(Modifier.fillMaxWidth().padding(16.dp)) { ... }
}

// ✅ Buono: remember per Modifier dinamico
@Composable
fun DynamicCard(color: Color) {
    val modifier = remember(color) {
        Modifier.fillMaxWidth().background(color)
    }
    Box(modifier) { ... }
}

Domande frequenti

Posso usare un singolo Modifier per più elementi Composable?

Sì, Modifier è immutabile, quindi un oggetto può essere utilizzato in sicurezza in più punti. Tuttavia, se usi un modificatore composed, ogni chiamata crea una nuova istanza. Per catene statiche, una costante o val fuori dal Composable è la soluzione ottimale.

Come eseguire il debug di una catena di modificatori?

Usa Layout Inspector in Android Studio — mostra visivamente i confini di ogni Modifier. Per il debugging programmatico, aggiungi Modifier.border() con diversi colori ad ogni passo della catena per vedere i confini di ogni modificatore.

Cosa è Modifier.then() e in cosa differisce dalle chiamate sequenziali?

Modifier.then(other) aggiunge la catena other a this. Le chiamate sequenziali (Modifier.a().b()) sono equivalenti a Modifier.then(a()).then(b()). Non c'è differenza — è lo stesso meccanismo di catena. then() è utile quando devi aggiungere una catena già pronta da una variabile.

In che modo Modifier influisce sulla semantica di Accessibilità?

Modifier.semantics {} definisce come l'elemento sarà descritto a uno screen reader. Modifier.clickable() aggiunge automaticamente il ruolo Pulsante e Action(OnClick). Per i gesti personalizzati, devi specificare esplicitamente semantics. Senza modificatori semantici, gli utenti di TalkBack non potranno interagire con componenti personalizzati.

Perché background in Modifier non funziona con angoli arrotondati?

Modifier.background(color, shape) funziona con gli angoli, ma clip() deve venire PRIMA di background affinché gli angoli vengano ritagliati. Ordine corretto: clip(shape).background(color). Se devi ritagliare anche il contenuto interno, usa clipToBounds() sul genitore.

Riepilogo

  • Modifier è un oggetto immutabile per descrivere dichiarativamente aspetto e comportamento
  • L'ordine dei modificatori determina il risultato: padding → clickable vs clickable → padding
  • Catena costruita sequenzialmente, ogni elemento avvolge il precedente
  • Modifier.composed permette di creare modificatori con stato e CompositionLocal
  • Prestazioni: sposta catene statiche in costanti, usa remember per quelle dinamiche
  • Semantica: Modifier.semantics è obbligatorio per l'Accessibilità di componenti personalizzati
  • Raccomandazione: disponi i modificatori dal layout alla decorazione, poi al comportamento

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