Le linee guida per la progettazione di app TV definiscono una variante di scheda
chiamata Scheda classica ampia,
che mostra un'immagine e il relativo blocco di contenuti descrittivi uno accanto all'altro.
Quando crei layout bidimensionali complessi per gli schermi TV, l'utilizzo del posizionamento tradizionale basato sulle coordinate o di contenitori Row e Column nidificati in profondità può rendere il codice difficile da leggere, gestire e sottoporre a refactoring.
La scheda classica ampia è un caso d'uso ideale per l'API Grid di Jetpack Compose, che ti aiuta a strutturare gli elementi affiancati in modo pulito utilizzando aree di layout 2D semantiche definite dall'utente.
Best practice
Implementa il layout della scheda con Grid.
L'utilizzo del contenitore Grid migliora la leggibilità del codice separando le dimensioni del layout fisico dal posizionamento degli elementi secondari.
Anziché fare affidamento sugli indici delle tracce esatti, definisci le aree semantiche denominate con la funzione area e posiziona i composable secondari con il modificatore gridItem.
Combina il dimensionamento flessibile delle tracce, ad esempio GridTrackSize.Auto
e minmax(0.dp, 1.fr),
con spazi tra le tracce esatti (gap(row = 8.dp, column = 16.dp))
per organizzare in modo chiaro e affidabile i componenti delle schede affiancate complesse.
Ingredienti
Grid: un layout di contenitore 2D in Jetpack Compose che dispone i composable secondari in righe e colonne in base a una lambda di configurazionegridItem: un'estensioneModifierche associa un elemento UI secondario a unareaIddenominato specifico all'interno di un layoutGridarea: una funzione DSL di configurazione all'interno diGridConfigurationScopeche mappa unareaIdsemantico a intervalli o intervalli di righe e colonne specificiCard: un composable di contenitore Material Design che raggruppa elementi UI e stili correlatiGridTrackSize.MinMax: una proprietà di dimensionamento delle tracce che definisce i limiti flessibili (minemax) per le dimensioni di righe o colonneGridTrackSize.Auto: una proprietà di dimensionamento delle tracce che dimensiona automaticamente la traccia di riga o colonna in modo che si adatti ai contenuti (column(GridTrackSize.Auto))gap: una funzione di configurazione che specifica la spaziatura verticale (row) e orizzontale (column) tra le tracce della griglia
Passaggi
Definisci gli identificatori delle aree, configura le tracce e le aree della griglia, quindi posiziona i composable secondari.
1. Definisci gli identificatori delle aree semantiche
Innanzitutto, crea una rappresentazione con tipo sicuro delle regioni all'interno del layout della scheda classica ampia. Una classe enum evita errori di battitura delle stringhe e fornisce sicurezza in fase di compilazione quando esegui il mapping delle tracce e posizioni gli elementi secondari.
enum class CardArea { Image, Title, Subtitle, Description, ExtraText, }
2. Configura le tracce della griglia 2D e le aree denominate
All'interno della lambda config del composable Grid, definisci le colonne e le righe che compongono la struttura della scheda. Utilizza GridTrackSize.Auto per la colonna dell'immagine in modo che il wrapping della larghezza della miniatura sia pulito. Utilizza minmax(0.dp, 1.fr) per la colonna dei contenuti in modo che si espanda in modo flessibile sulla larghezza rimanente della scheda. Specifica la spaziatura delle tracce con gap(row = 8.dp, column = 16.dp). Esegui il mapping degli identificatori CardArea alle relative coordinate delle tracce fisiche utilizzando la funzione area.
Grid( config = { // Define columns: left column for image, right for content column(GridTrackSize.Auto) column(minmax(0.dp, 1.fr)) // Define row tracks for the vertical content stack row(GridTrackSize.Auto) row(GridTrackSize.Auto) row(GridTrackSize.Auto) row(GridTrackSize.Auto) // Map semantic identifiers to grid coordinates and spans area(CardArea.Image, row = 1, column = 1, rowSpan = 4) area(CardArea.Title, row = 1, column = 2) area(CardArea.Subtitle, row = 2, column = 2) area(CardArea.Description, row = 3, column = 2) area(CardArea.ExtraText, row = 4, column = 2) gap(row = 8.dp, column = 16.dp) } ) { // Child elements placed in Step 3 }
3. Posiziona i composable secondari utilizzando il modificatore gridItem
Una volta configurate le tracce e le aree, posiziona ogni elemento UI secondario in base all'intento semantico utilizzando il modificatore gridItem. Puoi dichiarare i composable secondari in qualsiasi ordine. Il contenitore Grid posiziona automaticamente ogni elemento direttamente nella regione 2D assegnata.
@Composable fun WideClassicCard( imageContent: @Composable () -> Unit, title: String, subtitle: String, description: String, extraText: String, modifier: Modifier = Modifier, ) { Card(modifier = modifier) { Grid( config = { // Define columns: left column for image, right for content column(GridTrackSize.Auto) column(minmax(0.dp, 1.fr)) // Define row tracks for the vertical content stack row(GridTrackSize.Auto) row(GridTrackSize.Auto) row(GridTrackSize.Auto) row(GridTrackSize.Auto) // Map semantic identifiers to grid coordinates and spans area(CardArea.Image, row = 1, column = 1, rowSpan = 4) area(CardArea.Title, row = 1, column = 2) area(CardArea.Subtitle, row = 2, column = 2) area(CardArea.Description, row = 3, column = 2) area(CardArea.ExtraText, row = 4, column = 2) gap(row = 8.dp, column = 16.dp) }, ) { Box(modifier = Modifier.gridItem(CardArea.Image)) { imageContent() } Text( text = title, style = MaterialTheme.typography.titleLarge, modifier = Modifier .gridItem(CardArea.Title) .padding(top = 16.dp, end = 16.dp), ) Text( text = subtitle, style = MaterialTheme.typography.titleMedium, modifier = Modifier .gridItem(CardArea.Subtitle) .padding(end = 16.dp), ) Text( text = description, style = MaterialTheme.typography.bodyMedium, modifier = Modifier .gridItem(CardArea.Description) .padding(end = 16.dp), ) Text( text = extraText, style = MaterialTheme.typography.labelSmall, modifier = Modifier .gridItem(CardArea.ExtraText) .padding(bottom = 16.dp, end = 16.dp), ) } } }
Risultati
Organizzando la scheda classica ampia con Grid e le aree denominate, ottieni una separazione chiara tra le tracce del layout fisico, le coordinate delle aree e il posizionamento dei composable secondari.
Questa struttura rende il layout leggibile e gestibile, rispettando al contempo le linee guida per la progettazione di app TV per i componenti di miniature e descrizioni affiancati.
Risorse aggiuntive
- Linee guida per la progettazione di TV: schede
- Guida alle app adattive: proprietà del contenitore Grid