Creare un browser del catalogo

Un'app multimediale eseguita su una TV deve consentire agli utenti di sfogliare le sue offerte di contenuti, effettuare una selezione e iniziare a riprodurre i contenuti. L'esperienza di navigazione dei contenuti per app di questo tipo deve essere semplice, intuitiva, visivamente piacevole e coinvolgente.

Un browser di cataloghi multimediali tende a essere composto da diverse sezioni e ognuna ha un elenco di contenuti multimediali. Esempi di sezioni in un catalogo di contenuti multimediali includono: playlist, contenuti in primo piano, categorie consigliate.

Figura 1. Tipica schermata del catalogo. Gli utenti possono sfogliare i dati del catalogo video.

Usa le funzioni fornite da Compose per TV per implementare un'interfaccia utente per sfogliare la musica o i video dal catalogo multimediale della tua app.

Creare una funzione componibile per il catalogo

Tutto ciò che appare su un display è implementato come funzione componibile in Compose per TV. Per iniziare, definisci una funzione componibile per il browser Media Catalog:

@Composable
fun CatalogBrowser(
   featuredContentList: List<Movie>,
   sectionList: List<Section>,
   modifier: Modifier = Modifier,
   onItemSelected: (Movie) -> Unit = {},
) {
// ToDo: add implementation
}

CatalogBrowser è la funzione componibile che implementa il browser del catalogo multimediale. La funzione accetta i seguenti argomenti:

  • Elenco dei contenuti in primo piano.
  • Elenco delle sezioni.
  • Un oggetto Modificatore.
  • Una funzione di callback, che attiva una transizione sullo schermo.

Impostare gli elementi dell'interfaccia utente

Compose per TV offre elenchi lenti, un componente per visualizzare un numero elevato di elementi (o un elenco di lunghezza sconosciuta). Chiama TvLazyColumn per posizionare le sezioni in verticale. TvLazyColumn fornisce un blocco TvLazyListScope.() -> Unit, che offre un DSL per definire i contenuti degli articoli. Nell'esempio seguente, ogni sezione viene inserita in un elenco verticale con uno spazio di 16 dp tra le varie sezioni:

@Composable
fun CatalogBrowser(
   featuredContentList: List<Movie>,
   sectionList: List<Section>,
   modifier: Modifier = Modifier,
   onItemSelected: (Movie) -> Unit = {},
) {
  TvLazyColumn(
    modifier = modifier.fillMaxSize(),
    verticalArrangement = Arrangement.spacedBy(16.dp)
  ) {
    items(sectionList) { section ->
      Section(section, onItemSelected = onItemSelected)
    }
  }
}

Nell'esempio, la funzione componibile Section definisce come visualizzare le sezioni. Nella funzione seguente, TvLazyRow mostra come questa versione orizzontale di TvLazyColumn viene utilizzata in modo simile per definire un elenco orizzontale con un blocco TvLazyListScope.() -> Unit chiamando il DSL fornito:

@Composable
fun Section(
  section: Section,
  modifier: Modifier = Modifier,
  onItemSelected: (Movie) -> Unit = {},
) {
  Text(
    text = section.title,
    style = MaterialTheme.typography.headlineSmall,
  )
  TvLazyRow(
     modifier = modifier,
     horizontalArrangement = Arrangement.spacedBy(8.dp)
  ) {
    items(section.movieList){ movie ->
    MovieCard(
         movie = movie,
         onClick = { onItemSelected(movie) }
       )
    }
  }
}

Nel componibile Section viene utilizzato il componente Text. Il testo e altri componenti definiti in Material Design sono disponibili nella libreria tv-materiale . Puoi modificare lo stile dei testi come definito in Material Design facendo riferimento all'oggetto MaterialTheme. Questo oggetto è fornito anche dalla libreria tv-material. Card fa parte della raccolta tv-materiale. MovieCard definisce la modalità di rendering dei dati di ogni film nel catalogo definito come il seguente snippet:

@Composable
fun MovieCard(
   movie: Movie,
   modifier: Modifier = Modifier,
   onClick: () -> Unit = {}
) {
   Card(modifier = modifier, onClick = onClick){
    AsyncImage(
       model = movie.thumbnailUrl,
       contentDescription = movie.title,
     )
   }
}

Nell'esempio descritto in precedenza, tutti i film vengono visualizzati in modo uguale. Hanno la stessa area, ma non c'è alcuna differenza visiva. Puoi evidenziarne alcune con Carousel.

Carosello mostra le informazioni in un insieme di elementi che possono scorrere, in dissolvenza o spostare nella visualizzazione. Puoi utilizzare il componente per mettere in evidenza i contenuti in primo piano, come i film appena usciti o i nuovi episodi di programmi TV.

Carousel ti chiede di specificare almeno il numero di elementi del carosello e come disegnare ciascuno di essi. Il primo può essere specificato con itemCount. La seconda può essere trasmessa come lambda. Il numero di indice dell'elemento visualizzato viene dato al parametro lambda. Puoi determinare l'elemento visualizzato con il dato valore di indice:

@Composable
function FeaturedCarousel(
  featuredContentList: List<Movie>,
  modifier: Modifier = Modifier,
) {
  Carousel(
    itemCount = featuredContentList.size,
    modifier = modifier,
  ) { index ->
    val content = featuredContentList[index]
    Box {
      AsyncImage(
        model = content.backgroundImageUrl,
        contentDescription = content.description,
        placeholder = painterResource(
          id = R.drawable.placeholder
        ),
        contentScale = ContentScale.Crop,
        modifier = Modifier.fillMaxSize()
      )
      Text(text = content.title)
    }
  }
}

Carousel può essere un elemento di un elenco lento, come TvLazyColumn. Il seguente snippet mostra FeaturedCarousel componibile sopra tutti i componibili Section:

@Composable
fun CatalogBrowser(
   featuredContentList: List<Movie>,
   sectionList: List<Section>,
   modifier: Modifier = Modifier,
   onItemSelected: (Movie) -> Unit = {},
) {
  TvLazyColumn(
    modifier = modifier.fillMaxSize(),
    verticalArrangement = Arrangement.spacedBy(16.dp)
  ) {

    item {
      FeaturedCarousel(featuredContentList)
    }

    items(sectionList) { section ->
      Section(section, onItemSelected = onItemSelected)
    }
  }
}