Creare un browser del catalogo

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

Questa sezione descrive come utilizzare le funzioni fornite da Compose per la TV per implementare un'interfaccia utente per sfogliare musica o video dal catalogo multimediale dell'app.

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

Un browser di cataloghi multimediali tende a essere composto da diverse sezioni e ogni sezione include un elenco di contenuti multimediali. Tra le sezioni di un catalogo multimediale ci sono: playlist, contenuti in primo piano, categorie consigliate

Crea una funzione componibile per il catalogo

Tutto ciò che appare su un display è implementato come funzione componibile in Compose per la TV. Inizierai con la definizione di una funzione componibile per il browser del catalogo multimediale come il seguente snippet:

@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 tuo catalogo multimediale. La funzione accetta i seguenti argomenti:

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

Impostare gli elementi dell'interfaccia utente

Compose per la TV offre elenchi lenti, un componente per visualizzare un numero elevato di elementi (o un elenco di lunghezza sconosciuta). Chiamerai TvLazyColumn per posizionare le sezioni in verticale. TvLazyColumn fornisce un blocco TvLazyListScope.() -> Unit, che offre una connessione DSL per definire i contenuti degli elementi. Nell'esempio seguente, ogni sezione è inserita in un elenco verticale con un intervallo di 16 dp tra le 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 in che modo questa versione orizzontale di TvLazyColumn viene utilizzata in modo simile per definire un elenco orizzontale con un blocco TvLazyListScope.() -> Unit richiamando la DSL fornita.

@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 offerti nella raccolta di materiali televisivi . Puoi modificare lo stile dei testi come definito in Material Design facendo riferimento all'oggetto MaterialTheme. Questo oggetto è fornito anche dalla libreria tv-material. MovieCard definisce in che modo viene eseguito il rendering dei dati di ogni film nel catalogo definito come il seguente snippet. Anche Card fa parte della raccolta di materiali per la TV.

@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 filmati vengono visualizzati nello stesso modo. Hanno la stessa area, senza differenze visive tra loro. Puoi evidenziarne alcune con Carousel.

Il carosello mostra le informazioni in un insieme di elementi che possono essere scorrevoli, sbiaditi o visibili. Puoi utilizzare il componente per mettere in evidenza i contenuti in primo piano, come film appena disponibili o nuove puntate di programmi TV.

Carousel prevede che tu specifichi almeno il numero di elementi di Carousel e come disegnare ciascun elemento. Il primo può essere specificato con itemCount. Il secondo può essere passato come lambda. Il numero di indice dell'elemento visualizzato è dato alla funzione lambda. Puoi determinare l'elemento visualizzato con il valore di indice specificato.

@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. Lo snippet seguente mostra il componibile FeaturedCarousel 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)
    }
  }
}