In Compose, gli elementi dell'interfaccia utente sono rappresentati dalle funzioni componibili che, quando richiamati, emettono una parte dell'interfaccia utente che viene poi aggiunta a una struttura dell'interfaccia utente che viene 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 una posizione (x, y) e una dimensione, specificate come width
e height
.
I genitori definiscono i vincoli per gli elementi secondari. A un elemento viene chiesto di
definire le proprie dimensioni entro questi vincoli. I vincoli limitano il numero minimo e massimo di width
e height
di un elemento. Se un elemento ha elementi secondari, può misurare ogni elemento secondario per determinarne le dimensioni. Una volta che un elemento determina e ne registra le proprie dimensioni, ha l'opportunità di definire come posizionare gli elementi secondari rispetto a se stesso, come descritto in dettaglio nella sezione Creazione di layout personalizzati.
La disposizione di ciascun nodo nell'albero dell'interfaccia utente è un processo in tre passaggi. Ogni nodo deve:
- Misura i bambini
- Stabilire la propria dimensione
- Posiziona i relativi figli
L'utilizzo degli ambiti definisce quando è possibile misurare e posizionare i figli.
La misurazione di un layout può essere eseguita solo durante le operazioni di misurazione e layout e un elemento secondario può essere posizionato solo durante le fasi di misurazione del layout (e solo dopo che è stato misurato). A causa di 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 modalità di misurazione e 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 di questo componibile, passati come
constraints
. Un modificatore di layout personalizzato può avere questo aspetto:
fun Modifier.customLayoutModifier() = layout { measurable, constraints -> // ... }
Visualizza un elemento Text
sullo schermo e controlliamo la distanza dalla parte superiore
alla base di riferimento della prima riga di testo. Questa è esattamente la funzione del modificatore paddingFromBaseline
, che stiamo implementando qui come esempio.
A questo scopo, utilizza il modificatore layout
per posizionare manualmente il componibile sullo schermo. Ecco il comportamento desiderato in cui 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 succede nel codice:
- Nel parametro lambda
measurable
, misuri il valoreText
rappresentato dal parametro misurabile tramite la chiamata dimeasurable.measure(constraints)
. - Puoi specificare la dimensione del componibile chiamando il metodo
layout(width, height)
, che fornisce anche una funzione lambda utilizzata per posizionare gli elementi aggregati. In questo caso, è l'altezza tra l'ultima base di riferimento e la spaziatura interna superiore aggiunta. - Puoi posizionare gli elementi aggregati sullo schermo chiamando
placeable.place(x, y)
. Se gli elementi aggregati non vengono posizionati, non saranno visibili. La posizioney
corrisponde alla spaziatura interna superiore, ovvero la posizione della prima base di riferimento del testo.
Per verificare che funzioni come previsto, utilizza questo modificatore su 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)) } }
Crea layout personalizzati
Il modificatore layout
cambia solo il componibile di chiamata. Per misurare e layout
più elementi componibili, utilizza invece l'elemento componibile Layout
. Questo componibile consente di misurare e disporre i bambini manualmente. Tutti i layout di livello superiore, come Column
e Row
, sono creati con l'elemento componibile Layout
.
Creiamo una versione molto di base 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 // ... } }
In modo simile al modificatore layout
, measurables
è l'elenco dei figli che
devono essere misurati e constraints
sono i vincoli dell'elemento padre.
Seguendo la stessa logica di prima, MyBasicColumn
può essere implementato nel seguente 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 } } } }
Gli elementi componibili secondari sono vincolati dai vincoli Layout
(senza i vincoli minHeight
) e vengono posizionati in base al valore yPosition
dell'elemento componibile precedente.
Ecco come verrà utilizzato l'elemento componibile 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 layout
Cambia la direzione del layout di un componibile modificando la composizione locale di LocalLayoutDirection
.
Se inserisci manualmente i componibili sullo schermo, LayoutDirection
fa parte del LayoutScope
del modificatore layout
o del componibile Layout
.
Quando usi layoutDirection
, posiziona i componibili 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 Compose e osserva i layout personalizzati in azione in Esempi di Compose per creare layout personalizzati.
Scopri di più
Per scoprire di più sui layout personalizzati in Compose, consulta le seguenti risorse aggiuntive.
Video
Consigliato per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Misurazioni intrinseche nei layout di Compose
- Elementi grafici in Compose
- Modificatori di Scrivi