In Compose, puoi concatenare più modificatori per cambiare l'aspetto e il design di un componibile. Queste catene di modificatori possono influire sui vincoli trasmessi ai componibili, che definiscono i limiti di larghezza e altezza.
Questa pagina descrive in che modo i modificatori concatenati influiscono sui vincoli e, a loro volta, sulla misurazione e sul posizionamento dei componibili.
Modificatori nell'albero dell'interfaccia utente
Per capire come i modificatori si influenzano a vicenda, è utile visualizzare come vengono visualizzati nell'albero dell'interfaccia utente, che viene generato durante la fase di composizione. Per ulteriori informazioni, consulta la sezione Composizione.
Nell'albero dell'interfaccia utente, puoi visualizzare i modificatori come nodi wrapper per i nodi di layout:
![Codice per i componibili e i modificatori e la loro rappresentazione visiva come albero dell'interfaccia utente.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/modifier-wrapping.png?authuser=5&hl=it)
L'aggiunta di più di un modificatore a un componibile crea una catena di modificatori. Quando concateni più modificatori, ogni nodo di modifica aggrega il resto della catena e il nodo di layout al suo interno. Ad esempio, quando concateni un clip
e un modificatore
size
, il nodo del modificatore clip
racchiude il nodo modificatore size
,
che a sua volta aggrega il nodo di layout Image
.
Nella fase di layout, l'algoritmo che cammina sull'albero rimane lo stesso, ma viene visitato anche ogni nodo modificatore. In questo modo, un modificatore può cambiare i requisiti di dimensioni e il posizionamento del nodo di modifica o layout che aggrega.
Come mostrato nella Figura 2, l'implementazione degli elementi componibili Image
e Text
stessalmente consiste in una catena di modificatori che aggregano un singolo nodo di layout. Le
implementazioni di Row
e Column
sono semplicemente nodi di layout che descrivono come
il layout secondario.
![La struttura ad albero di prima, ma ora ogni nodo è solo un layout semplice, circondato da numerosi nodi di modificatori.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/composables-modifiers.png?authuser=5&hl=it)
In sintesi:
- I modificatori aggregano un singolo nodo di modifica o layout.
- I nodi di layout possono disporre più nodi figlio.
Le sezioni seguenti descrivono come utilizzare questo modello mentale per ragionare sul concatenamento dei modificatori e su come questo influenza le dimensioni dei componibili.
Vincoli nella fase di layout
La fase di layout segue un algoritmo in tre passaggi per trovare la larghezza, l'altezza e la coordinata x e y di ogni nodo di layout:
- Misura gli elementi secondari: un nodo misura i relativi figli, se presenti.
- Decidi la tua dimensione: in base a queste misurazioni, un nodo decide autonomamente le proprie dimensioni.
- Posiziona elementi secondari: ogni nodo figlio viene posizionato rispetto alla posizione di un nodo.
Constraints
aiuta a trovare le dimensioni giuste per i nodi durante i primi due passaggi dell'algoritmo. I vincoli definiscono i limiti minimo e massimo per la larghezza e l'altezza di un nodo. Quando il nodo decide le proprie dimensioni, quelle misurate
devono rientrare in questo intervallo.
Tipi di vincoli
Un vincolo può essere uno dei seguenti:
- Delimitato: il nodo ha larghezza e altezza massime e minime.
![Vincoli limitati di dimensioni diverse all'interno di un container.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/bounded-constraints.png?authuser=5&hl=it)
- Illimitata: il nodo non è vincolato a nessuna dimensione. I limiti di larghezza e altezza massime sono impostati su infinito.
![I vincoli illimitati con larghezza e altezza impostate su infinito. I vincoli si estendono oltre il container.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/unbounded-constraints.png?authuser=5&hl=it)
- Esatta: il nodo deve seguire un requisito di dimensione esatto. I limiti minimo e massimo vengono impostati sullo stesso valore.
![Vincoli esatti che si adattano a un esatto requisito di dimensioni all'interno del contenitore.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/exact-constraints.png?authuser=5&hl=it)
- Combinazione: il nodo segue una combinazione dei tipi di vincoli precedenti. Ad esempio, un vincolo potrebbe limitare la larghezza consentendo al contempo un'altezza massima illimitata oppure impostare una larghezza esatta, ma fornire un'altezza limitata.
![Due container che mostrano combinazioni di vincoli limitati e illimitati e larghezze e altezze esatte.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/combination-constraints.png?authuser=5&hl=it)
Nella prossima sezione viene descritto il modo in cui questi vincoli vengono passati da un elemento padre a un figlio.
Modalità di trasferimento dei vincoli da elementi principali a elementi secondari
Nel primo passaggio dell'algoritmo descritto in Vincoli nella fase di layout, i vincoli vengono passati da elementi padre a figlio nella struttura dell'interfaccia utente.
Quando un nodo padre misura i relativi elementi figlio, fornisce questi vincoli a ciascuno dei nodi figlio per comunicare loro quanto possono essere grandi o piccoli. Poi, quando decide la propria dimensione, aderisce anche ai vincoli trasmessi dai propri padre.
A livello generale, l'algoritmo funziona nel seguente modo:
- Per decidere le dimensioni che vuole effettivamente occupare, il nodo radice nell'albero dell'interfaccia utente misura i relativi elementi secondari e inoltra gli stessi vincoli al primo elemento figlio.
- Se il publisher secondario è un modificatore che non influisce sulla misurazione, inoltra i vincoli al modificatore successivo. I vincoli vengono trasmessi dalla catena di modifica così com'è, a meno che non venga raggiunto un modificatore che influisce sulla misurazione. I vincoli vengono quindi ridimensionati di conseguenza.
- Una volta raggiunto un nodo privo di elementi figlio (denominato "nodo foglia "), determina le dimensioni in base ai vincoli trasmessi e restituisce questa dimensione risolta all'elemento padre.
- L'elemento principale adatta i propri vincoli in base alle misurazioni di questo asset secondario e chiama il figlio successivo con questi vincoli modificati.
- Dopo aver misurato tutti gli elementi secondari di un nodo padre, il nodo padre decide la propria dimensione e la comunica al proprio padre.
- In questo modo, l'intero albero viene attraversato in profondità. Alla fine, tutti i nodi hanno deciso le loro dimensioni e la fase di misurazione è stata completata.
Per un esempio approfondito, guarda il video Vincoli e ordine dei modificatori.
Modificatori che influiscono sui vincoli
Nella sezione precedente hai imparato che alcuni modificatori possono influire sulle dimensioni dei vincoli. Le seguenti sezioni descrivono i modificatori specifici che influiscono sui vincoli.
Modificatore size
Il modificatore size
dichiara la dimensione preferita dei contenuti.
Ad esempio, la seguente struttura di UI dovrebbe essere visualizzata in un container di 300dp
per 200dp
. I vincoli sono limitati, consentendo larghezze comprese tra 100dp
e
300dp
e altezze comprese tra 100dp
e 200dp
:
![Una parte di un albero dell'interfaccia utente con il modificatore di dimensione che racchiude un nodo di layout e la
rappresentazione dei vincoli limitati impostati dal modificatore di dimensione in un container.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/size-modifier.png?authuser=5&hl=it)
Il modificatore size
adatta i vincoli in entrata in modo che corrispondano al valore trasmesso.
In questo esempio, il valore è 150dp
:
![Come nella Figura 7, tranne per il fatto che il modificatore di dimensione adatta i vincoli in entrata in modo che corrispondano al valore trasmesso.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/size-modifier-2.png?authuser=5&hl=it)
size
regola i vincoli su 150dp
.Se la larghezza e l'altezza sono inferiori al vincolo minimo associato o superiori al vincolo più grande, il modificatore associa il più possibile i vincoli trasmessi, rispettando al contempo i vincoli trasmessi:
![Due strutture di UI e le relative rappresentazioni nei container. Nel primo, il modificatore di dimensione accetta i vincoli in aumento, mentre nel secondo si adatta il più possibile ai vincoli troppo grandi, generando vincoli che riempiono il container.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/size-modifier-3.png?authuser=5&hl=it)
size
rispetta il vincolo passato il più fedelmente
possibile.Tieni presente che concatenare più modificatori size
non funziona. Il primo modificatore size
imposta i vincoli minimo e massimo su un valore fisso. Anche se il secondo modificatore di dimensione richiede una dimensione maggiore o minore, deve comunque rispettare i limiti esatti trasmessi, in modo da non sostituire questi valori:
![Una catena di due modificatori di dimensione nell'albero dell'interfaccia utente e la sua rappresentazione in un container,
ovvero il risultato del primo valore trasmesso e non del secondo.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/size-modifier-4.png?authuser=5&hl=it)
size
, in cui il secondo valore trasmesso (50dp
) non sostituisce il primo valore (100dp
).Modificatore requiredSize
Utilizza il modificatore requiredSize
anziché size
se vuoi che il nodo sostituisca i vincoli in entrata. Il modificatore requiredSize
sostituisce
i vincoli in entrata e trasmette le dimensioni specificate come limiti esatti.
Quando la dimensione viene passata di nuovo nell'albero, il nodo figlio viene centrato nello spazio disponibile:
![Il modificatore size e obbligatorioSize concatenati in un albero dell'interfaccia utente e la rappresentazione
corrispondente in un container. I vincoli del modificatore di dimensione requiredSize sostituiscono quelli del modificatore
di dimensione.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/requiredsize-modifier.png?authuser=5&hl=it)
requiredSize
che sostituisce i vincoli in entrata
dal modificatore size
.Modificatori width
e height
Il modificatore size
adatta sia la larghezza che l'altezza dei vincoli. Con
il modificatore width
, puoi impostare una larghezza fissa, ma lasciare incerta l'altezza.
Allo stesso modo, con il tasto di modifica height
puoi impostare un'altezza fissa, ma lasciare indecisa la larghezza:
![Due strutture di interfaccia utente, una con il modificatore di larghezza e la relativa rappresentazione del container e l'altra con il modificatore di altezza e la relativa rappresentazione.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/width-height-modifier.png?authuser=5&hl=it)
width
e il modificatore height
impostano rispettivamente una larghezza e un'altezza fisse.Modificatore sizeIn
Il modificatore sizeIn
consente di impostare i vincoli minimo e massimo esatti per la larghezza e l'altezza. Usa il modificatore sizeIn
se hai bisogno di un controllo granulare sui vincoli.
![Un albero dell'interfaccia utente con il modificatore sizeIn con larghezze e altezze minime e massime impostate e la relativa rappresentazione all'interno di un container.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/sizein-modifier.png?authuser=5&hl=it)
sizeIn
con minWidth
, maxWidth
, minHeight
e
maxHeight
impostati.Esempi
Questa sezione mostra e spiega l'output di diversi snippet di codice con modificatori concatenati.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .size(50.dp) )
Questo snippet produce il seguente output:
- Il modificatore
fillMaxSize
modifica i vincoli per impostare la larghezza e l'altezza minime sul valore massimo:300dp
per la larghezza e200dp
per l'altezza. - Anche se il modificatore
size
vuole utilizzare una dimensione di50dp
, deve comunque rispettare i vincoli minimi in entrata. Di conseguenza, il modificatoresize
restituirà anche gli esatti limiti del vincolo di300
entro il giorno200
, ignorando di fatto il valore fornito nel modificatoresize
. Image
segue questi limiti e riporta una dimensione di300
per200
, che viene superata fino alla fine dell'albero.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .wrapContentSize() .size(50.dp) )
Questo snippet produce il seguente output:
- Il modificatore
fillMaxSize
adatta i vincoli per impostare sia la larghezza che l'altezza minima al valore massimo:300dp
per la larghezza e200dp
per l'altezza. - Il modificatore
wrapContentSize
reimposta i vincoli minimi. Pertanto, anche sefillMaxSize
ha generato vincoli fissi,wrapContentSize
lo reimposta ai vincoli limitati. Il seguente nodo ora può occupare di nuovo l'intero spazio o essere più piccolo dell'intero spazio. - Il modificatore
size
imposta i vincoli sui limiti minimo e massimo di50
. - Il valore
Image
viene risolto nella dimensione50
per50
e il modificatoresize
inoltra questo risultato. - Il modificatore
wrapContentSize
ha una proprietà speciale. Prende il proprio figlio e lo pone al centro dei limiti minimi disponibili che gli sono stati concessi. Le dimensioni che comunica agli elementi padre corrispondono quindi ai limiti minimi superati.
Combinando solo tre modificatori, è possibile definire una dimensione per il componibile e centrarla nel relativo elemento padre.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .clip(CircleShape) .padding(10.dp) .size(100.dp) )
Questo snippet produce il seguente output:
- Il modificatore
clip
non modifica i vincoli.- Il modificatore
padding
riduce i vincoli massimi. - Il modificatore
size
imposta tutti i vincoli su100dp
. Image
aderisce a questi vincoli e registra una dimensione di100
per100dp
.- Il modificatore
padding
aggiunge10dp
a tutte le dimensioni, quindi aumenta la larghezza e l'altezza riportate di20dp
. - Ora nella fase di disegno, il modificatore
clip
agisce su un canvas di120
di120dp
. Quindi, crea una maschera circolare di quella dimensione. - Il modificatore
padding
inserisce quindi i propri contenuti per10dp
su tutte le dimensioni, quindi riduce le dimensioni del canvas a100
per100dp
. - L'elemento
Image
viene disegnato in quell'area di lavoro. L'immagine viene ritagliata in base al cerchio originale di120dp
, quindi l'output è un risultato non arrotondato.
- Il modificatore