In Compose, gli elementi UI sono rappresentati dalle funzioni componibili che, quando vengono richiamate, emettono una parte della UI, che viene poi aggiunta a un albero UI che viene visualizzato 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 dimensione, specificata come width e height.
Gli elementi principali definiscono i vincoli per i relativi elementi secondari. A un elemento viene chiesto di definire le sue dimensioni entro questi vincoli. I vincoli limitano i valori minimi e massimi di width e height di un elemento. Se un elemento ha elementi secondari, può misurare ciascun elemento secondario per determinare le proprie dimensioni. Una volta che un elemento determina e segnala le proprie dimensioni, ha l'opportunità di definire come posizionare i propri elementi secondari rispetto a se stesso, come descritto in dettaglio in Creazione di layout personalizzati.
La disposizione di ogni nodo nell'albero della UI è un processo in tre passaggi. Ogni nodo deve:
- Misura i bambini
- Decidere le proprie dimensioni
- Posiziona i relativi elementi secondari
L'utilizzo degli ambiti definisce quando puoi misurare e posizionare i tuoi elementi secondari.
La misurazione di un layout può essere eseguita solo durante le fasi di misurazione e layout, mentre un elemento secondario può essere posizionato solo durante le fasi 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.
Utilizza il modificatore di layout
Puoi utilizzare il modificatore layout per modificare il modo in cui un elemento viene misurato e disposto. Layout è una funzione lambda; i suoi parametri includono l'elemento che puoi misurare,
passato come measurable, e i vincoli in entrata dell'elemento composable, passati come
constraints. Un modificatore di layout personalizzato può avere il seguente aspetto:
fun Modifier.customLayoutModifier() = layout { measurable, constraints -> // ... }
Visualizza un Text sullo schermo e controlla la distanza dalla parte superiore alla linea di base della prima riga di testo. Questo è esattamente ciò che fa il modificatore paddingFromBaseline; lo stai implementando qui come esempio.
Per farlo, utilizza il modificatore layout per posizionare manualmente il componibile sullo schermo. Ecco il comportamento risultante quando il padding superiore di Text è impostato su 24.dp:
paddingFromBaseline applicato.
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, misuri il valoreTextrappresentato dal parametro misurabile chiamandomeasurable.measure(constraints). - Puoi specificare le dimensioni del componibile chiamando il metodo
layout(width, height), che fornisce anche una funzione lambda utilizzata per posizionare gli elementi aggregati. In questo caso, si tratta dell'altezza tra l'ultima base di riferimento e il padding superiore aggiunto. - Puoi posizionare gli elementi con wrapping sullo schermo chiamando
placeable.place(x, y). Se gli elementi con wrapping non vengono posizionati, non saranno visibili. La posizioneycorrisponde al padding superiore, ovvero alla posizione della prima 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)) } }
Text e visualizzato in anteprima.
Crea layout personalizzati
Il modificatore layout modifica solo l'elemento composable chiamante. Per misurare e disporre più componibili, utilizza invece il componibile Layout. Questo componibile
ti consente di misurare e disporre manualmente gli elementi secondari. Tutti i layout di livello superiore come Column e Row sono creati con il componibile Layout.
Questo esempio crea 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 degli elementi secondari che devono essere misurati e constraints sono i vincoli dell'elemento principale.
Seguendo 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 al yPosition del composabile precedente.
Ecco come verrebbe utilizzato questo 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!") } }
Column.
Direzione del layout
Modifica la direzione del layout di un composable modificando il valore locale della composizione LocalLayoutDirection.
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 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 guarda i layout personalizzati in azione negli esempi di Compose che creano layout personalizzati.
Scopri di più
Per scoprire di più sui layout personalizzati in Compose, 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
- Modificatori di Compose