Jetpack Compose semplifica notevolmente la progettazione e la creazione dell'interfaccia utente della tua app. Compose trasforma lo stato in elementi dell'interfaccia utente tramite:
- Composizione degli elementi
- Layout degli elementi
- Disegno di elementi
Questo documento si concentra sul layout degli elementi e illustra alcuni degli elementi di base di Compose che ti aiutano a progettare gli elementi dell'interfaccia utente.
Scopi dei layout in Scrivi
L'implementazione del sistema di layout di Jetpack Compose ha due obiettivi principali:
- Elevate prestazioni
- Possibilità di scrivere facilmente layout personalizzati
Nozioni di base sulle funzioni componibili
Le funzioni componibili sono l'elemento di base di Compose. Una funzione componibile è una funzione che emette Unit
e descrive una parte dell'interfaccia utente. La funzione accetta alcuni input e genera ciò che viene mostrato sullo schermo. Per ulteriori informazioni sui composabili, consulta la documentazione del modello mentale di composizione.
Una funzione componibile potrebbe emettere diversi elementi dell'interfaccia utente. Tuttavia, se non fornisci indicazioni su come devono essere disposti, Scrivi potrebbe disporre gli elementi in un modo che non ti piace. Ad esempio, questo codice genera due elementi di testo:
@Composable fun ArtistCard() { Text("Alfred Sisley") Text("3 minutes ago") }
Se non fornisci indicazioni su come vuoi disporli, Scrivi impila gli elementi di testo uno sopra l'altro, rendendoli illeggibili:
Compose fornisce una raccolta di layout pronti all'uso per aiutarti a organizzare gli elementi dell'interfaccia utente e semplifica la definizione di layout personalizzati e più specializzati.
Componenti del layout standard
In molti casi, puoi semplicemente utilizzare gli elementi di layout standard di Compose.
Utilizza
Column
per posizionare gli elementi verticalmente sullo schermo.
@Composable fun ArtistCardColumn() { Column { Text("Alfred Sisley") Text("3 minutes ago") } }
Analogamente, utilizza
Row
per posizionare gli elementi orizzontalmente sullo schermo. Sia Column
che Row
supportano la configurazione dell'allineamento degli elementi che contengono.
@Composable fun ArtistCardRow(artist: Artist) { Row(verticalAlignment = Alignment.CenterVertically) { Image(bitmap = artist.image, contentDescription = "Artist image") Column { Text(artist.name) Text(artist.lastSeenOnline) } } }
Utilizza Box
per sovrapporre gli elementi. Box
supporta anche la configurazione di un allineamento specifico degli elementi che contiene.
@Composable fun ArtistAvatar(artist: Artist) { Box { Image(bitmap = artist.image, contentDescription = "Artist image") Icon(Icons.Filled.Check, contentDescription = "Check mark") } }
Spesso questi elementi di base sono tutto ciò di cui hai bisogno. Puoi scrivere la tua funzione composable per combinare questi layout in un layout più elaborato adatto alla tua app.
Per impostare la posizione dei figli all'interno di un Row
, imposta gli argomenti horizontalArrangement
e
verticalAlignment
. Per un Column
, imposta gli argomenti verticalArrangement
e
horizontalAlignment
:
@Composable fun ArtistCardArrangement(artist: Artist) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.End ) { Image(bitmap = artist.image, contentDescription = "Artist image") Column { /*...*/ } } }
Il modello di layout
Nel modello di layout, l'albero dell'interfaccia utente viene visualizzato in un unico passaggio. A ogni nodo viene prima chiesto di misurarsi, poi di misurare gli eventuali elementi secondari in modo ricorsivo, passando i vincoli di dimensione alla gerarchia. Poi, le dimensioni e il posizionamento dei nodi a foglia vengono impostati e le istruzioni per le dimensioni e il posizionamento risolte vengono ritrasmesse all'albero.
In breve, i genitori si misurano prima dei figli, ma le loro misure e la loro posizione vengono inserite dopo quelle dei figli.
Considera la seguente funzione SearchResult
.
@Composable fun SearchResult() { Row { Image( // ... ) Column { Text( // ... ) Text( // ... ) } } }
Questa funzione genera la seguente struttura dell'interfaccia utente.
SearchResult
Row
Image
Column
Text
Text
Nell'esempio SearchResult
, il layout dell'albero dell'interfaccia utente segue questo ordine:
- Viene chiesto di misurare il nodo principale
Row
. - Il nodo principale
Row
chiede al suo primo elemento secondario,Image
, di eseguire la misurazione. Image
è un nodo foglia (ovvero non ha elementi secondari), pertanto riporta una dimensione e restituisce le istruzioni di posizionamento.- Il nodo principale
Row
chiede al secondo nodo figlio,Column
, di eseguire la misurazione. - Il nodo
Column
chiede al primo elemento secondarioText
di eseguire la misurazione. - Il primo nodo
Text
è un nodo foglia, quindi riporta una dimensione e restituisce istruzioni di posizionamento. - Il nodo
Column
chiede al secondo nodo figlioText
di eseguire la misurazione. - Il secondo nodo
Text
è un nodo foglia, quindi riporta una dimensione e restituisce le istruzioni di posizionamento. - Ora che il nodo
Column
ha misurato, definito le dimensioni e posizionato i suoi elementi secondari, può determinare le proprie dimensioni e il proprio posizionamento. - Ora che il nodo principale
Row
ha misurato, definito le dimensioni e posizionato i propri nodi secondari, può determinare le proprie dimensioni e il proprio posizionamento.
Prestazioni
Compose raggiunge prestazioni elevate misurando i bambini una sola volta. La misurazione con un solo passaggio è ottima per le prestazioni, in quanto consente a Compose di gestire in modo efficiente gli alberi dell'interfaccia utente complessi. Se un elemento misurasse il proprio elemento figlio due volte e questo misurasse ciascuno dei suoi elementi figlio due volte e così via, un singolo tentativo di progettare un'intera UI richiederebbe molto lavoro, rendendo difficile mantenere il rendimento dell'app.
Se per qualche motivo il layout richiede più misurazioni, Compose offre un sistema speciale, le misure intrinseche. Puoi scoprire di più su questa funzionalità in Misurazioni intrinseche nei layout di Compose.
Poiché la misurazione e il posizionamento sono sottofasi distinte del passaggio del layout, eventuali modifiche che influiscono solo sul posizionamento degli elementi, non sulla misurazione, possono essere eseguite separatamente.
Utilizzare i modificatori nei layout
Come discusso in Modificatori di composizione, puoi utilizzare i modificatori per decorare o aumentare i tuoi composabili. I modificatori sono essenziali per personalizzare il layout. Ad esempio, qui abbiamo collegato diversi modificatori per personalizzare ArtistCard
:
@Composable fun ArtistCardModifiers( artist: Artist, onClick: () -> Unit ) { val padding = 16.dp Column( Modifier .clickable(onClick = onClick) .padding(padding) .fillMaxWidth() ) { Row(verticalAlignment = Alignment.CenterVertically) { /*...*/ } Spacer(Modifier.size(padding)) Card( elevation = CardDefaults.cardElevation(defaultElevation = 4.dp), ) { /*...*/ } } }
Nel codice riportato sopra, noterai diverse funzioni di modificatore utilizzate insieme.
clickable
fa in modo che un composable reagisca all'input dell'utente e mostri un'eco.padding
inserisce uno spazio intorno a un elemento.fillMaxWidth
fa in modo che il composable raggiunga la larghezza massima assegnata dall'elemento principale.size()
specifica la larghezza e l'altezza preferite di un elemento.
Layout scorrevoli
Scopri di più sui layout scorrevoli nella documentazione relativa ai gesti di composizione.
Per gli elenchi e gli elenchi lazy, consulta la documentazione relativa alla composizione degli elenchi.
Layout adattabili
Un layout deve essere progettato tenendo conto di diversi orientamenti dello schermo e dimensioni del fattore di forma. Compose offre già alcuni meccanismi per facilitare l'adattamento dei layout composable a varie configurazioni dello schermo.
Vincoli
Per conoscere le limitazioni provenienti dal componente principale e progettare il layout di conseguenza, puoi utilizzare un BoxWithConstraints
. I limiti di misurazione
si trovano nell'ambito della lambda dei contenuti. Puoi utilizzare queste limitazioni di misurazione per comporre layout diversi per configurazioni dello schermo diverse:
@Composable fun WithConstraintsComposable() { BoxWithConstraints { Text("My minHeight is $minHeight while my maxWidth is $maxWidth") } }
Layout basati su slot
Compose fornisce una vasta gamma di composable basati su Material Design con la dipendenza androidx.compose.material:material
(inclusa durante la creazione di un progetto Compose in Android Studio) per semplificare la creazione dell'interfaccia utente. Sono forniti elementi come
Drawer
,
FloatingActionButton
,
e TopAppBar
.
I componenti Material fanno un uso intensivo delle API di slot, un pattern introdotto da Compose per aggiungere un livello di personalizzazione ai composabili. Questo approccio consente di
creare componenti più flessibili, in quanto accettano un elemento secondario che può configurarsi
da solo, anziché dover esporre ogni parametro di configurazione del componente secondario.
Gli slot lasciano uno spazio vuoto nell'interfaccia utente che lo sviluppatore può riempire a piacere. Ad esempio, questi sono gli slot che puoi personalizzare in un
TopAppBar
:
I composabili in genere accettano un lambda composable ( content: @Composable
() -> Unit
). Le API di slot espongono più parametri content
per utilizzi specifici.content
Ad esempio, TopAppBar
ti consente di fornire i contenuti per title
,
navigationIcon
e actions
.
Ad esempio,
Scaffold
consente di implementare un'interfaccia utente con la struttura di layout di base di Material Design.
Scaffold
fornisce gli slot per i componenti Material di primo livello più comuni,
come TopAppBar
,
BottomAppBar
,
FloatingActionButton
,
e Drawer
. Con Scaffold
è facile assicurarsi che questi componenti siano posizionati correttamente e collaborino in modo corretto.
@Composable fun HomeScreen(/*...*/) { ModalNavigationDrawer(drawerContent = { /* ... */ }) { Scaffold( topBar = { /*...*/ } ) { contentPadding -> // ... } } }
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Modificatori di composizione
- Kotlin per Jetpack Compose
- Componenti e layout di Material