In Compose, gli elementi dell'interfaccia utente sono rappresentati dalle funzioni componibili che emettono un
pezzo di UI quando vengono richiamate, che viene poi aggiunto a un albero dell'interfaccia utente visualizzato sullo
schermo. Ogni elemento UI ha un elemento padre e potenzialmente molti elementi secondari. Ogni
elemento si trova anche all'interno del relativo elemento principale, specificato come posizione (x, y), e
ha una dimensione, specificata come width
e height
.
I genitori definiscono i vincoli per gli elementi secondari. A un elemento viene chiesto di
definire le proprie dimensioni all'interno di questi vincoli. I vincoli limitano il minimo e
il massimo di width
e height
di un elemento. Se un elemento ha elementi secondari, può
misurare ciascun elemento secondario per determinare le dimensioni. Una volta che un elemento determina
e segnala le proprie dimensioni, ha l'opportunità di definire come posizionare i suoi elementi
figli rispetto a se stesso, come descritto in dettaglio nella sezione Creazione di layout
personalizzati.
La disposizione di ogni nodo nell'albero dell'interfaccia utente è una procedura in tre passaggi. Ogni nodo deve:
- Misurare i bambini
- Decidere le proprie dimensioni
- Posiziona i suoi figli
L'utilizzo degli ambiti definisce quando puoi misurare e posizionare i tuoi figli.
La misurazione di un layout può essere eseguita solo durante le passate di misurazione e layout
e un elemento secondario può essere posizionato solo durante le passate 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 del layout
Puoi utilizzare il modificatore layout
per modificare la modalità di misurazione e disposizione di un elemento. Layout
è una lambda; i suoi parametri includono l'elemento che puoi misurare,
passato come measurable
, e i vincoli in entrata del componibile, passati come
constraints
. Un modificatore di layout personalizzato può avere il seguente aspetto:
fun Modifier.customLayoutModifier() = layout { measurable, constraints -> // ... }
Visualizziamo un Text
sullo schermo e controlliamo la distanza dalla parte superiore alla
linea di base della prima riga di testo. È esattamente quello che fa il modificatore
paddingFromBaseline
, che implementiamo qui come esempio.
Per farlo, utilizza il modificatore layout
per posizionare manualmente il composable sullo schermo. Ecco il comportamento desiderato in cui viene impostato il padding superiore Text
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 succede in questo codice:
- Nel parametro lambda
measurable
, misuriText
rappresentato dal parametro misurabile chiamandomeasurable.measure(constraints)
. - Specifichi le dimensioni del componibile chiamando il metodo
layout(width, height)
, che fornisce anche un'espressione lambda utilizzata per posizionare gli elementi di wrapping. In questo caso, è l'altezza tra l'ultima linea di base e la spaziatura interna superiore aggiunta. - Posiziona gli elementi di wrapping sullo schermo chiamando
placeable.place(x, y)
. Se gli elementi di wrapping non vengono posizionati, non saranno visibili. La posizioney
corrisponde al riempimento 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 disporre
più composable, utilizza invece il composable Layout
. Questo elemento componibile
ti consente di misurare e disporre i figli manualmente. Tutti i layout di livello superiore
come Column
e Row
sono creati con il componente Layout
.
Creiamo una versione molto semplice di Column
. La maggior parte dei layout personalizzati segue questo
pattern:
@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 dei figli che
devono essere misurati e constraints
sono i vincoli del genitore.
Seguendo la stessa logica di prima, MyBasicColumn
può essere implementato come segue:
@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 composable figlio sono vincolati dai vincoli Layout
(senza i vincoli
minHeight
) e vengono posizionati in base a yPosition
del
composable precedente.
Ecco come verrebbe utilizzato questo 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
Modifica la direzione del layout di un elemento componibile modificando la
LocalLayoutDirection
composizione locale.
Se posizioni manualmente gli elementi componibili sullo schermo, LayoutDirection
fa parte di LayoutScope
del modificatore layout
o dell'elemento componibile Layout
.
Quando utilizzi layoutDirection
, posiziona i composable utilizzando place
. A differenza del metodo
placeRelative
, place
non cambia in base alla direzione del layout
(da sinistra a destra e da destra a sinistra).
Layout personalizzati in azione
Scopri di più su layout e modificatori in Layout di base in Compose e guarda i layout personalizzati in azione in Esempi di Compose che creano layout personalizzati.
Scopri di più
Per saperne di più sui layout personalizzati in Crea, 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 Composizione
- Modificatori di composizione