Vincoli e ordine dei modificatori

In Compose, puoi concatenare più modificatori per cambiare l'aspetto e un'immagine componibile. 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:

Codice per i componibili e i modificatori e la loro rappresentazione visiva come albero dell'interfaccia utente.
Figura 1. Modificatori che racchiudono i nodi di layout nell'albero dell'interfaccia utente.

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 colleghi un modificatore clip e un modificatore size, il nodo modificatore clip avvolge il nodo modificatore size, che a sua volta avvolge il nodo 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.

La struttura ad albero di prima, ma ora ogni nodo è solo un layout semplice, con molti nodi di modifica che lo avvolgono.
Figura 2. La stessa struttura ad albero della Figura 1, ma con gli elementi componibili nella Albero dell'UI visualizzato come catene di modificatori.

In sintesi:

  • I modificatori aggregano un singolo nodo di modifica o layout.
  • I nodi di layout possono presentare più nodi figlio.

Le seguenti sezioni descrivono come usare questo modello mentale per ragionare concatenamento dei modificatori e su come questo influisce sulle 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 del layout:

  1. Misura i figli: un nodo misura i suoi figli, se presenti.
  2. Decide le proprie dimensioni: in base a queste misurazioni, un nodo decide autonomamente le proprie dimensioni.
  3. Posiziona i nodi secondari: ogni nodo secondario 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 minimi e massimi per la larghezza e l'altezza di un nodo. Quando il nodo decide le proprie dimensioni, le dimensioni misurate devono rientrare in questo intervallo di dimensioni.

Tipi di vincoli

Una limitazione può essere una delle seguenti:

  • Contenuto: il nodo ha una larghezza e un'altezza massime e minime.
Vincoli limitati di dimensioni diverse all'interno di un container.
Figura 3. Vincoli con limiti.
  • Senza limiti: il nodo non è vincolato a nessuna dimensione. La larghezza massima e i limiti di altezza sono impostati su infinito.
I vincoli illimitati con larghezza e altezza impostate su infinito. I vincoli si estendono oltre il contenitore.
Figura 4. Vincoli non vincolati.
  • Esatta: al nodo viene chiesto di rispettare un requisito di dimensioni esatto. Il minimo e i limiti massimi siano impostati sullo stesso valore.
Vincoli esatti che si adattano a un esatto requisito di dimensioni all'interno del contenitore.
Figura 5. Vincoli esatti.
  • Combinazione: il nodo segue una combinazione dei tipi di vincoli precedenti. Ad esempio, un vincolo potrebbe limitare la larghezza consentendo al contempo altezza massima illimitata oppure imposta una larghezza esatta, ma fornisci un'altezza limitata.
Due container che mostrano combinazioni di vincoli limitati e illimitati e larghezze e altezze esatte.
Figura 6. Combinazioni di vincoli con limiti e senza limiti e larghezze e altezze esatte.

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 principale misura i suoi figli, fornisce questi vincoli a ciascun figlio per fargli sapere quanto può essere grande o piccolo. Poi, decide la propria dimensione, inoltre rispetta i vincoli trasmessi i propri genitori.

A livello generale, l'algoritmo funziona nel seguente modo:

  1. 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.
  2. Se il publisher secondario è un modificatore che non influisce sulla misurazione, inoltra al modificatore successivo. I vincoli vengono passati al modificatore catena così com'è, a meno che non venga raggiunto un modificatore che influisce sulla misurazione. Le limitazioni vengono quindi ridimensionate di conseguenza.
  3. Una volta raggiunto un nodo che non ha figli (chiamato anche " nodo"), determina le dimensioni in base ai vincoli trasmessi e restituisce questa dimensione risolta all'elemento principale.
  4. L'elemento principale adatta i vincoli in base alle misurazioni dell'elemento secondario e chiama l'elemento secondario successivo con questi vincoli aggiustati.
  5. Una volta misurati tutti gli elementi secondari di un elemento padre, il nodo padre decide dimensioni proprie e la comunica al proprio genitore.
  6. In questo modo, l'intero albero viene attraversato in 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 seguenti sezioni descrivono i modificatori specifici che influiscono i 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. di 200dp. I vincoli sono limitati e consentono 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
  rappresentazione dei vincoli limitati impostati dal modificatore di dimensione in un container.
Figura 7. Vincoli limitati nell'albero dell'interfaccia utente e relativa rappresentazione in un container.

Il modificatore size adatta le limitazioni in entrata in modo che corrispondano al valore che gli viene passato. 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.
Figura 8. Il modificatore size che regola i vincoli in 150dp.

Se la larghezza e l'altezza sono inferiori al limite inferiore del vincolo o superiori al limite superiore del vincolo, il modificatore corrisponde il più possibile ai vincoli passati rispettando al contempo i vincoli passati:

Due alberi dell'interfaccia utente e le relative rappresentazioni in contenitori. Nel primo,
  il modificatore di dimensione accetta i vincoli in aumento; nella seconda, il modificatore di dimensione si adatta
  i vincoli troppo grandi il più vicino possibile, con conseguenti vincoli che riempiono il contenitore.
Figura 9. Il modificatore size che rispetta il vincolo passato il più possibile.

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:

Una catena di due modificatori di dimensione nell'albero dell'interfaccia utente e la sua rappresentazione in un container.
  che è il risultato del primo valore passato e non del secondo.
Figura 10. Una catena di due modificatori size, in cui il secondo valore passato (50dp) non sostituisce il primo valore (100dp).

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 passa la dimensione specificata come limiti esatti.

Quando la dimensione viene ritrasmessa nell'albero, il nodo figlio sarà centrato di spazio disponibile:

Le dimensioni e il modificatore di dimensione richiesto concatenati in un albero dell'interfaccia utente e i valori corrispondenti
  rappresentazione in un container. I vincoli del modificatore di dimensione requiredSize sostituiscono il modificatore di dimensione
  i vincoli.
Figura 11. Il modificatore requiredSize ha sostituito i vincoli in entrata del modificatore size.

Modificatori width e height

Il modificatore size adatta sia la larghezza che l'altezza dei vincoli. Con il tasto di modifica 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 lascia il valore larghezza indecisa:

Due alberi dell'interfaccia utente, uno con il modificatore di larghezza e la relativa rappresentazione del contenitore e l'altro con il modificatore di altezza e la relativa rappresentazione.
Figura 12. Il modificatore 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 larghezza e altezza. Usa il modificatore sizeIn se hai bisogno di un controllo granulare rispetto ai 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 contenitore.
Figura 13. Il modificatore sizeIn con minWidth, maxWidth, minHeight e maxHeight impostato.

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, ovvero 300dp in larghezza e 200dp in altezza.
  • Anche se il modificatore size vuole utilizzare una dimensione di 50dp, deve comunque per rispettare i vincoli minimi in entrata. Pertanto, il modificatore size genererà anche i limiti esatti del vincolo di 300 per 200, ignorando di fatto il valore fornito nel modificatore size.
  • Image segue questi limiti e riporta una dimensione di 300 x 200, 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, ovvero 300dp in larghezza e 200dp in altezza.
  • Il modificatore wrapContentSize reimposta i vincoli minimi. Quindi, mentre fillMaxSize ha generato vincoli fissi, wrapContentSize lo reimposta di nuovo a vincoli limitati. 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 di 50.
  • Image si risolve in una dimensione di 50 x 50 e il modificatore size lo inoltra.
  • Il modificatore wrapContentSize ha una proprietà speciale. Prende la sua secondario e lo pone al centro dei limiti minimi disponibili che erano le abbiamo passate. Le dimensioni comunicate ai relativi elementi principali sono quindi uguali ai limiti minimi che sono stati passati.

Combinando solo tre modificatori, è possibile definire la dimensione dell'elemento al centro dell'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 i vincoli.
    • Il modificatore padding riduce i vincoli massimi.
    • Il modificatore size imposta tutti i vincoli su 100dp.
    • Image rispetta questi vincoli e indica una dimensione di 100 per 100dp.
    • Il modificatore padding aggiunge 10dp su tutte le dimensioni, quindi aumenta il valore riportato larghezza e altezza di 20dp.
    • Ora nella fase di disegno, il modificatore clip agisce su un canvas di 120. 120dp. Quindi, crea una maschera circolare di quella dimensione.
    • Il modificatore padding inserisce quindi i contenuti per 10dp su tutte le dimensioni, quindi abbassa le dimensioni della tela a 100 per 100dp.
    • L'elemento Image viene disegnato in quell'area di lavoro. L'immagine viene ritagliata in base cerchio originale di 120dp, quindi l'output è un risultato non arrotondato.