Vincoli e ordine dei modificatori

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.
Figura 1. Modificatori che inseriscono i nodi di layout nell'albero dell'interfaccia utente.

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.
Figura 2. La stessa struttura ad albero della Figura 1, ma con elementi componibili nell'albero dell'interfaccia utente visualizzati come catene di modificatori.

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:

  1. Misurare gli elementi secondari: un nodo misura gli eventuali elementi figlio.
  2. Stabilisci la dimensione personalizzata: in base a queste misurazioni, un nodo decide la propria dimensione.
  3. 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.
Figura 3. Vincoli limitati.
  • 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.
Figura 4. Vincoli illimitati.
  • 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.
Figura 5. Vincoli esatti.
  • 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.
Figura 6. Combinazioni di vincoli limitati e illimitati e larghezze e altezze esatte.

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:

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. Dopo aver misurato tutti i figli di un nodo, il nodo padre decide le proprie dimensioni e le comunica al proprio padre.
  6. 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.
Figura 7. Vincoli limitati nella struttura dell'interfaccia utente e la sua rappresentazione in un container.

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.
Figura 8. Il modificatore 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.
Figura 9. Il modificatore 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.
Figura 10. Una catena di due modificatori 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.
Figura 11. Il modificatore 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.
Figura 12. Il modificatore 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.
Figura 13. Modificatore 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, ovvero 300dp per larghezza e 200dp per altezza.
  • Anche se il modificatore size vuole utilizzare una dimensione pari a 50dp, deve comunque rispettare i vincoli minimi previsti. Di conseguenza, il modificatore size restituirà anche gli esatti limiti del vincolo di 300 entro il campo 200, ignorando di fatto il valore fornito nel modificatore size.
  • Image segue questi limiti e segnala una dimensione pari a 300 per 200, 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, ovvero 300dp per la larghezza e 200dp per l'altezza.
  • Il modificatore wrapContentSize reimposta i vincoli minimi. Quindi, sebbene fillMaxSize 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 di 50.
  • Il valore Image viene risolto in 50 in base alla dimensione 50 e il modificatore size 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 su 100dp.
    • Image rispetta questi vincoli e segnala una dimensione pari a 100 entro il giorno 100dp.
    • Il modificatore padding aggiunge 10dp per tutte le dimensioni, in modo da aumentare la larghezza e l'altezza segnalate di 20dp.
    • In fase di disegno, il modificatore clip agisce su un canvas di 120 di 120dp. Viene quindi creata una maschera circolare di quelle dimensioni.
    • Il modificatore padding inserisce quindi i propri contenuti in base a 10dp in tutte le dimensioni, riducendo così le dimensioni della tela a 100 di 100dp.
    • Il Image è disegnato nella tela. L'immagine è ritagliata in base al cerchio originale di 120dp, quindi l'output è un risultato non arrotondato.