In Compose, puoi concatenare più modificatori per modificare l'aspetto e l'aspetto di un componibile. Queste catene di modificatori possono influenzare i vincoli passati ai componibili, che definiscono i limiti di larghezza e altezza.
Questa pagina descrive in che modo i modificatori concatenati influenzano i vincoli e, a loro volta, la misurazione e il posizionamento degli elementi componibili.
Modificatori nell'albero dell'interfaccia utente
Per capire in che modo i modificatori si influenzano a vicenda, è utile visualizzare come vengono visualizzati nell'albero dell'interfaccia utente, generato durante la fase di composizione. Per ulteriori informazioni, consulta la sezione Composizione.
Nella struttura ad albero dell'interfaccia utente, puoi visualizzare i modificatori come nodi wrapper per i nodi di layout:
![Codice per componibili e modificatori e relativa rappresentazione visiva come albero dell'interfaccia utente.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/modifier-wrapping.png?authuser=3&hl=it)
L'aggiunta di più modificatori 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, se concateni clip
e un modificatore
size
, il nodo del modificatore clip
inserisce un a capo nel nodo del modificatore size
, che a sua volta aggrega il nodo di layout Image
.
Nella fase di layout, l'algoritmo che cammina nell'albero rimane invariato, ma viene visitato anche ogni nodo di modifica. In questo modo, un modificatore può cambiare i requisiti di dimensione e il posizionamento del modificatore o del nodo di layout.
Come mostrato nella Figura 2, l'implementazione degli elementi componibili Image
e Text
in sé consiste in una catena di modificatori che avvolgono un singolo nodo di layout. Le implementazioni di Row
e Column
sono semplicemente nodi di layout che descrivono come strutturare i nodi figlio.
![La struttura ad albero di prima, ma ora ogni nodo è semplicemente un layout semplice, circondato da molti nodi con wrapping di modificatori.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/composables-modifiers.png?authuser=3&hl=it)
Riassumendo:
- I modificatori aggregano un singolo modificatore o nodo di layout.
- I nodi di layout possono disporre più nodi secondari.
Le seguenti sezioni descrivono come usare 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 le coordinate x e y di ogni nodo di layout:
- Misurare gli elementi secondari: un nodo misura gli eventuali elementi figlio.
- Stabilisci la dimensione personalizzata: in base a queste misurazioni, un nodo decide la propria dimensione.
- Posiziona elementi figlio: ogni nodo figlio viene posizionato in relazione 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 a decidere le sue dimensioni, la dimensione misurata deve rientrare in questo intervallo.
Tipi di vincoli
Un vincolo può essere uno dei seguenti:
- Associato: 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=3&hl=it)
- Non limitato: il nodo non è vincolato a nessuna dimensione. I limiti massimi di larghezza e altezza sono impostati su infinito.
![Vincoli non limitati 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=3&hl=it)
- Esatta: il nodo deve rispettare un requisito di dimensioni esatto. I limiti minimo e massimo sono impostati sullo stesso valore.
![Vincoli esatti conformi a un requisito di dimensioni esatto all'interno del container.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/exact-constraints.png?authuser=3&hl=it)
- Combinazione: il nodo segue una combinazione dei tipi di vincolo precedenti. Ad esempio, un vincolo può limitare la larghezza consentendo un'altezza massima illimitata oppure impostare una larghezza esatta, ma fornire un'altezza limitata.
![Due contenitori 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=3&hl=it)
La sezione successiva descrive il modo in cui questi vincoli vengono trasferiti da un elemento padre a uno secondario.
Come passare i vincoli da un elemento padre all'altro
Durante il primo passaggio dell'algoritmo descritto in Vincoli nella fase di layout, i vincoli vengono trasmessi da padre a figlio nella struttura ad albero dell'interfaccia utente.
Quando un nodo padre misura i suoi figli, fornisce questi vincoli a ciascuno per indicare quanto possono essere grandi o piccoli che possono essere. Poi, quando decide le proprie dimensioni, aderisce anche ai vincoli trasmessi dai genitori.
A livello generale, l'algoritmo funziona nel seguente modo:
- Per decidere le dimensioni effettive che intende occupare, il nodo radice nell'albero dell'interfaccia utente misura i relativi elementi secondari e inoltra gli stessi vincoli al primo elemento figlio.
- Se l'elemento figlio è un modificatore che non influisce sulla misurazione, inoltra i vincoli al modificatore successivo. I vincoli vengono trasmessi dalla catena di modificatori così com'è, a meno che non venga raggiunto un modificatore che influisce sulla misurazione. I vincoli vengono quindi ridimensionati di conseguenza.
- Quando viene raggiunto un nodo che non ha elementi secondari (chiamato "nodo foglia "), ne decide le dimensioni in base ai vincoli che sono stati 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 richiama l'elemento secondario successivo con questi vincoli regolati.
- Dopo aver misurato tutti i figli di un nodo, il nodo padre decide le proprie dimensioni e le comunica al proprio padre.
- In questo modo, l'intero albero viene attraversato in profondità. Alla fine, tutti i nodi hanno deciso le proprie dimensioni e la fase di misurazione è stata completata.
Per un esempio dettagliato, guarda il video Vincoli e ordine dei modificatori.
Modificatori che influiscono sui vincoli
Nella sezione precedente hai imparato che alcuni modificatori possono influire sulla dimensione del vincolo. Le seguenti sezioni descrivono modificatori specifici che influiscono sui vincoli.
Modificatore size
Il modificatore size
dichiara le dimensioni preferite dei contenuti.
Ad esempio, la seguente struttura dell'interfaccia utente dovrebbe essere visualizzata in un container 300dp
entro 200dp
. I vincoli sono limitati e consentono larghezze comprese tra 100dp
e 300dp
e altezze comprese tra 100dp
e 200dp
:
![Parte di una struttura ad albero dell'interfaccia utente con il modificatore di dimensione che inserisce un nodo di layout e la rappresentazione dei vincoli vincolati impostati dal modificatore di dimensione in un container.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/size-modifier.png?authuser=3&hl=it)
Il modificatore size
adatta i vincoli in entrata in modo che corrispondano al valore che gli viene trasmesso.
In questo esempio, il valore è 150dp
:
![Come nella Figura 7, ad eccezione del 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=3&hl=it)
size
che modifica i vincoli in 150dp
.Se la larghezza e l'altezza sono minori del limite del vincolo minimo o maggiore del limite del vincolo più grande, il modificatore corrisponde il più fedelmente possibile ai vincoli passati, pur rispettando i vincoli passati:
![Due strutture dell'interfaccia utente e le rappresentazioni corrispondenti nei container. Nel primo, il modificatore di dimensione accetta i vincoli incrementali, mentre nel secondo si adatta il più fedelmente possibile ai vincoli di dimensione troppo grandi, creando vincoli per riempire il container.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/size-modifier-3.png?authuser=3&hl=it)
size
che rispetta il vincolo passato il più fedelmente
possibile.Tieni presente che il concatenamento di più modificatori size
non funziona. Il primo modificatore di size
imposta i vincoli minimo e massimo su un valore fisso. Anche se
il secondo modificatore di dimensione richiede una dimensione inferiore o superiore, deve comunque rispettare
i limiti esatti trasmessi, quindi non sostituirà questi valori:
![Una catena di due modificatori di dimensione nella struttura ad albero dell'interfaccia utente e la sua rappresentazione in un container,
che è 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=3&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 hai bisogno che il nodo esegua l'override dei vincoli in entrata. Il modificatore requiredSize
sostituisce i vincoli in entrata e trasmette le dimensioni specificate come limiti esatti.
Quando le dimensioni vengono passate di nuovo all'albero, il nodo figlio sarà centrato nello spazio disponibile:
![Il modificatore di dimensione e obbligatorio size concatenati in una struttura dell'interfaccia utente e la rappresentazione corrispondente in un container. I vincoli del modificatore di dimensione obbligatori sostituiscono i vincoli dei modificatori delle dimensioni.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/requiredsize-modifier.png?authuser=3&hl=it)
requiredSize
sostituisce i vincoli in entrata dal modificatore size
.Modificatori width
e height
Il modificatore size
adatta sia la larghezza sia l'altezza dei vincoli. Con
il modificatore width
, puoi impostare una larghezza fissa, ma lasciare indeciso l'altezza.
Analogamente, con il modificatore height
puoi impostare un'altezza fissa, ma lasciare indecisa la larghezza:
![Due strutture UI, una con il modificatore di larghezza e la relativa rappresentazione del contenitore 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=3&hl=it)
width
e il modificatore height
impostano rispettivamente larghezza
e altezza fisse.Modificatore sizeIn
Il modificatore sizeIn
consente di impostare vincoli minimi e massimi esatti per larghezza e altezza. Utilizza il modificatore sizeIn
se hai bisogno di un controllo granulare sui vincoli.
![Una struttura ad albero dell'interfaccia utente con il modificatore sizeIn con larghezza e altezze minime e massime impostate e la relativa rappresentazione all'interno di un contenitore.](https://developer.android.com/static/develop/ui/compose/images/layouts/constraints-modifiers/sizein-modifier.png?authuser=3&hl=it)
sizeIn
con minWidth
, maxWidth
, minHeight
e
maxHeight
impostato.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, ovvero300dp
per larghezza e200dp
per altezza. - Anche se il modificatore
size
vuole utilizzare una dimensione pari a50dp
, deve comunque rispettare i vincoli minimi previsti. Di conseguenza, il modificatoresize
restituirà anche gli esatti limiti del vincolo di300
entro il campo200
, ignorando di fatto il valore fornito nel modificatoresize
. Image
segue questi limiti e segnala una dimensione pari a300
per200
, che viene passata fino in fondo all'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 la larghezza e l'altezza minime sul valore massimo, ovvero300dp
per la larghezza e200dp
per l'altezza. - Il modificatore
wrapContentSize
reimposta i vincoli minimi. Quindi, sebbenefillMaxSize
abbia generato vincoli fissi,wrapContentSize
lo reimposta nuovamente ai vincoli limitati. Il nodo seguente può ora 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 in50
in base alla dimensione50
e il modificatoresize
la inoltra. - Il modificatore
wrapContentSize
ha una proprietà speciale. Prende il figlio e lo colloca al centro dei limiti minimi disponibili che gli sono stati passati. Le dimensioni che comunica ai suoi elementi padre corrispondono quindi ai limiti minimi che sono stati passati al suo interno.
Combinando solo tre modificatori, puoi definire una dimensione per l'elemento 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 cambia i vincoli.- Il modificatore
padding
abbassa i vincoli massimi. - Il modificatore
size
imposta tutti i vincoli su100dp
. Image
rispetta questi vincoli e segnala una dimensione pari a100
entro il giorno100dp
.- Il modificatore
padding
aggiunge10dp
per tutte le dimensioni, in modo da aumentare la larghezza e l'altezza segnalate di20dp
. - In fase di disegno, il modificatore
clip
agisce su un canvas di120
di120dp
. Viene quindi creata una maschera circolare di quelle dimensioni. - Il modificatore
padding
inserisce quindi i propri contenuti in base a10dp
in tutte le dimensioni, riducendo così le dimensioni della tela a100
di100dp
. - Il
Image
è disegnato nella tela. L'immagine è ritagliata in base al cerchio originale di120dp
, quindi l'output è un risultato non arrotondato.
- Il modificatore