In Compose, gli elementi dell'interfaccia utente sono rappresentati dalle funzioni composable che emettono un frammento di interfaccia utente quando vengono richiamate, che viene poi aggiunto a una struttura ad albero dell'interfaccia utente visualizzata sullo schermo. Ogni elemento UI ha un elemento principale e potenzialmente molti elementi secondari. Ogni elemento si trova anche all'interno del relativo elemento principale, specificato come posizione (x, y) e come dimensione, specificata come width
e height
.
I genitori definiscono i vincoli per gli elementi secondari. A un elemento viene chiesto di
definire le sue dimensioni entro questi vincoli. I vincoli limitano i valori minimi e massimi width
e height
di un elemento. Se un elemento ha elementi secondari, può misurare ciascuno di questi per determinare le relative dimensioni. Una volta che un elemento determina e segnala le proprie dimensioni, ha la possibilità di definire come posizionare i propri elementi secondari rispetto a se stesso, come descritto in dettaglio in Creare layout personalizzati.
La disposizione di ogni nodo nell'albero dell'interfaccia utente è una procedura in tre passaggi. Ogni nodo deve:
- Misura tutti i bambini
- Decidere le proprie dimensioni
- Inserisci i figli
L'utilizzo degli ambiti definisce quando puoi misurare e posizionare i tuoi figli.
La misurazione di un layout può essere eseguita solo durante i passaggi di misurazione e di layout, mentre un elemento secondario può essere posizionato solo durante i passaggi di layout (e solo dopo essere stato misurato). A causa degli ambiti di Compose come
MeasureScope
e PlacementScope
,
questo viene applicato in fase di compilazione.
Utilizzare il modificatore di layout
Puoi utilizzare il modificatore layout
per modificare la misurazione e la disposizione di un elemento. Layout
è una funzione lambda; i suoi parametri includono l'elemento che puoi misurare, passato come measurable
, e i vincoli in entrata del composable, passati come constraints
. Un modificatore del layout personalizzato può avere il seguente aspetto:
fun Modifier.customLayoutModifier() = layout { measurable, constraints -> // ... }
Mostriamo un Text
sullo schermo e controlliamo la distanza dalla parte superiore alla linea di base della prima riga di testo. Questo è esattamente ciò che fa il modificatore paddingFromBaseline
. In questo caso, lo stiamo implementando come esempio.
A questo scopo, utilizza il tasto di modifica layout
per posizionare manualmente il componibile sullo
schermo. Ecco il comportamento desiderato quando la spaziatura interna superiore Text
è impostata su 24.dp
:
Ecco il codice per produrre questa spaziatura:
fun Modifier.firstBaselineToTop( firstBaselineToTop: Dp ) = layout { measurable, constraints -> // Measure the composable val placeable = measurable.measure(constraints) // Check the composable has a first baseline check(placeable[FirstBaseline] != AlignmentLine.Unspecified) val firstBaseline = placeable[FirstBaseline] // Height of the composable with padding - first baseline val placeableY = firstBaselineToTop.roundToPx() - firstBaseline val height = placeable.height + placeableY layout(placeable.width, height) { // Where the composable gets placed placeable.placeRelative(0, placeableY) } }
Ecco cosa sta succedendo nel codice:
- Nel parametro lambda
measurable
, misuri ilText
rappresentato dal parametro misurabile chiamandomeasurable.measure(constraints)
. - Specifichi le dimensioni del componibile chiamando il
layout(width, height)
metodo, che fornisce anche un lambda utilizzato per posizionare gli elementi con wrapping. In questo caso, è l'altezza tra l'ultima linea di base e la spaziatura interna superiore aggiunta. - Posiziona gli elementi a capo sullo schermo chiamando
placeable.place(x, y)
. Se gli elementi a capo non vengono posizionati, non saranno visibili. La posizioney
corrisponde al padding superiore, ovvero alla posizione della prima linea di base del testo.
Per verificare che funzioni come previsto, utilizza questo modificatore su un Text
:
@Preview @Composable fun TextWithPaddingToBaselinePreview() { MyApplicationTheme { Text("Hi there!", Modifier.firstBaselineToTop(32.dp)) } } @Preview @Composable fun TextWithNormalPaddingPreview() { MyApplicationTheme { Text("Hi there!", Modifier.padding(top = 32.dp)) } }
Creare layout personalizzati
Il modificatore layout
modifica solo il composable di chiamata. Per misurare e creare il layout di più composabili, utilizza invece il composable Layout
. Questo composable consente di misurare e disporre manualmente gli elementi secondari. Tutti i layout di livello superiore come Column
e Row
sono creati con il composable Layout
.
Creiamo una versione molto basilare di Column
. La maggior parte dei layout personalizzati segue questo
schema:
@Composable fun MyBasicColumn( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout( modifier = modifier, content = content ) { measurables, constraints -> // measure and position children given constraints logic here // ... } }
Analogamente al modificatore layout
, measurables
è l'elenco degli elementi secondari che devono essere misurati e constraints
sono i vincoli dell'elemento principale.
Seguindo la stessa logica di prima, MyBasicColumn
può essere implementato in questo modo:
@Composable fun MyBasicColumn( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout( modifier = modifier, content = content ) { measurables, constraints -> // Don't constrain child views further, measure them with given constraints // List of measured children val placeables = measurables.map { measurable -> // Measure each children measurable.measure(constraints) } // Set the size of the layout as big as it can layout(constraints.maxWidth, constraints.maxHeight) { // Track the y co-ord we have placed children up to var yPosition = 0 // Place children in the parent layout placeables.forEach { placeable -> // Position item on the screen placeable.placeRelative(x = 0, y = yPosition) // Record the y co-ord placed up to yPosition += placeable.height } } } }
I composabili secondari sono vincolati dai vincoli Layout
(senza i vincoli minHeight
) e vengono posizionati in base a yPosition
del composable precedente.
Ecco come verrà utilizzato il composable personalizzato:
@Composable fun CallingComposable(modifier: Modifier = Modifier) { MyBasicColumn(modifier.padding(8.dp)) { Text("MyBasicColumn") Text("places items") Text("vertically.") Text("We've done it by hand!") } }
Direzione del layout
Cambia la direzione del layout di un componibile modificando la
composizione locale di LocalLayoutDirection
.
Se posizioni manualmente gli elementi composibili sullo schermo, LayoutDirection
fa parte di LayoutScope
del modificatore layout
o dell'elemento componibile Layout
.
Quando utilizzi layoutDirection
, inserisci i composabili utilizzando place
. A differenza del metodo
placeRelative
, place
non cambia in base alla direzione del layout
(da sinistra a destra o da destra a sinistra).
Layout personalizzati in azione
Scopri di più su layout e modificatori in Layout di base in Componi e visualizza i layout personalizzati in azione in Esempi di Componi che creano layout personalizzati.
Scopri di più
Per scoprire di più sui layout personalizzati in Scrivi, consulta le seguenti risorse aggiuntive.
Video
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Misurazioni intrinseche nei layout di Compose
- Grafica in Compose
- Modifica modificatori