In Compose, puoi concatenare più modificatori per cambiare l'aspetto di un composable. Queste catene di modificatori possono influire sui vincoli passati ai composabili, che definiscono i limiti di larghezza e altezza.
Questa pagina descrive in che modo i modificatori in catena influiscono sui vincoli e, a loro volta, sulla misurazione e sul posizionamento dei composabili.
Modificatori nell'albero dell'interfaccia utente
Per capire in che modo i modificatori si influenzano a vicenda, è utile visualizzare come vengono visualizzati nella struttura ad albero dell'interfaccia utente, generata durante la fase di composizione. Per maggiori informazioni, consulta la sezione Composizione.
Nella struttura ad albero dell'interfaccia utente, puoi visualizzare i modificatori come nodi wrapper per i nodi di layout:
L'aggiunta di più di un modificatore a un componibile crea una catena di modificatori. Quando concatenate più modificatori, ogni nodo modificatore chiude il resto della catena e il nodo 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 esamina l'albero rimane invariato, ma viene visitato anche ogni nodo modificatore. In questo modo, un modificatore può modificare i requisiti di dimensione e il posizionamento del modificatore o del nodo di layout che avvolge.
Come mostrato nella Figura 2, l'implementazione dei composabili Image
e Text
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 disporre i relativi elementi secondari.
In sintesi:
- I modificatori racchiudono un singolo modificatore o nodo di layout.
- I nodi di layout possono presentare più nodi figlio.
Le sezioni seguenti descrivono come utilizzare questo modello mentale per ragionare sulla catena di modificatori e su come influisce sulle dimensioni dei composabili.
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 del layout:
- Misura gli elementi secondari: un nodo misura i relativi figli, se presenti.
- Decide le proprie dimensioni: 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
aiutano 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:
- Contenuto: il nodo ha una larghezza e un'altezza massime e minime.
- Senza limiti: il nodo non è vincolato a nessuna dimensione. I limiti massimi di larghezza e altezza sono impostati su infinito.
- Esatta: al nodo viene chiesto di rispettare un requisito di dimensioni esatto. I limiti minimo e massimo sono impostati sullo stesso valore.
- 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.
La sezione successiva descrive come questi vincoli vengono trasmessi da un elemento principale a uno secondario.
Come vengono trasmessi i vincoli dal gruppo principale a quello secondario
Durante il primo passaggio dell'algoritmo descritto in Limiti nella fase di layout, i vincoli vengono trasmessi dal nodo principale a quello secondario nella struttura ad albero dell'interfaccia utente.
Quando un nodo padre misura i relativi elementi figlio, fornisce questi vincoli a ciascun elemento figlio per comunicare loro quanto possono essere grandi o piccoli. Poi, quando decide le proprie dimensioni, rispetta anche le limitazioni passate dai suoi elementi principali.
A livello generale, l'algoritmo funziona nel seguente modo:
- Per decidere le dimensioni che vuole effettivamente occupare, il nodo principale dell'albero dell'interfaccia utente misura i suoi figli e inoltra gli stessi vincoli al primo 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.
- Quando viene raggiunto un nodo che non ha figli (chiamato "nodo foglia"), ne viene decisa la dimensione in base ai vincoli passati e questa dimensione viene restituita al nodo principale.
- L'elemento principale adatta i vincoli in base alle misurazioni dell'elemento secondario e chiama l'elemento secondario successivo con questi vincoli aggiustati.
- 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 ordine di profondità. Alla fine, tutti i nodi hanno scelto le proprie dimensioni e il passaggio di misurazione è stato completato.
Per un esempio dettagliato, guarda il video Limiti e ordine dei modificatori.
Modificatori che influiscono sui vincoli
Nella sezione precedente hai appreso che alcuni modificatori possono influire sulle dimensioni delle limitazioni. Le sezioni seguenti descrivono modificatori specifici che influiscono su i vincoli.
Modificatore size
Il modificatore size
dichiara le dimensioni preferite dei contenuti.
Ad esempio, la seguente struttura dell'interfaccia utente deve essere visualizzata in un contenitore di 300dp
per 200dp
. I vincoli sono limitati, consentendo larghezze comprese tra 100dp
e
300dp
e altezze comprese tra 100dp
e 200dp
:
Il modificatore size
adatta le limitazioni in entrata in modo che corrispondano al valore che gli viene passato.
In questo esempio, il valore è 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:
Tieni presente che l'accodamento di più modificatori size
non funziona. Il primo modificatore size
imposta i vincoli minimo e massimo su un valore fisso. Anche se il secondo modificatore delle dimensioni richiede una dimensione più piccola o più grande, deve comunque rispettare i limiti esatti passati, quindi non sostituirà questi valori:
Modificatore requiredSize
Utilizza il modificatore requiredSize
anziché size
se vuoi che il tuo node sostituisca i vincoli in entrata. Il modificatore requiredSize
sostituisce
i vincoli in entrata e trasmette le dimensioni specificate come limiti esatti.
Quando le dimensioni vengono ritrasmesse nella struttura ad albero, il nodo secondario viene centrato nello spazio disponibile:
Modificatori width
e height
Il modificatore size
adatta sia la larghezza che l'altezza delle limitazioni. Con il modificatore width
, puoi impostare una larghezza fissa, ma lasciare l'altezza indefinita.
Analogamente, con il modificatore height
puoi impostare un'altezza fissa, ma lasciare la larghezza indecisa:
Modificatore sizeIn
Il modificatore sizeIn
consente di impostare i vincoli minimo e massimo esatti per la larghezza e l'altezza. Utilizza il modificatore sizeIn
se hai bisogno di un controllo granulare
sui vincoli.
Esempi
Questa sezione mostra e spiega l'output di diversi snippet di codice con modifici in catena.
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .size(50.dp) )
Questo snippet produce il seguente output:
- Il modificatore
fillMaxSize
modifica le limitazioni per impostare sia la larghezza minima che l'altezza minima sul valore massimo, ovvero300dp
in larghezza e200dp
in altezza. - Anche se il modificatore
size
vuole utilizzare una dimensione di50dp
, deve comunque rispettare i vincoli minimi in entrata. Pertanto, il modificatoresize
genererà anche i limiti esatti del vincolo di300
per200
, ignorando di fatto il valore fornito nel modificatoresize
. Image
segue questi limiti e riporta una dimensione di300
x200
, che viene passata fino alla cima 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 le limitazioni per impostare sia la larghezza minima che l'altezza minima sul valore massimo, ovvero300dp
in larghezza e200dp
in altezza. - Il modificatore
wrapContentSize
reimposta i vincoli minimi. Pertanto, mentrefillMaxSize
ha generato vincoli fissi,wrapContentSize
li reimposta su vincoli con limiti. Il nodo successivo ora può occupare di nuovo tutto lo spazio o essere più piccolo dell'intero spazio. - Il modificatore
size
imposta i vincoli sui limiti minimo e massimo di50
. Image
si risolve in una dimensione di50
x50
e il modificatoresize
lo inoltra.- 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 comunicate ai relativi elementi principali sono quindi uguali ai limiti minimi che sono stati passati.
Combinando solo tre modificatori, puoi definire una dimensione per il composable e centrarlo nel relativo elemento principale.
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 le limitazioni.- Il modificatore
padding
riduce le limitazioni massime. - Il modificatore
size
imposta tutti i vincoli su100dp
. Image
rispetta questi vincoli e indica una dimensione di100
per100dp
.- Il modificatore
padding
aggiunge10dp
a tutte le dimensioni, quindi aumenta la larghezza e l'altezza registrate di20dp
. - Ora, nella fase di disegno, il modificatore
clip
agisce su una tela di120
per120dp
. Quindi, crea una maschera circolare di quella dimensione. - Il modificatore
padding
inserisce quindi i contenuti per10dp
su tutte le dimensioni, quindi abbassa la dimensione della tela a100
per100dp
. - Il carattere
Image
viene disegnato in quel canvas. L'immagine viene ritagliata in base al cerchio originale di120dp
, pertanto l'output è un risultato non arrotondato.
- Il modificatore