Cómo crear un navegador de catálogos

Una app de contenido multimedia que se ejecuta en una TV debe permitir que los usuarios exploren sus ofertas de contenido, hagan una selección y comiencen a reproducir contenido. La experiencia de navegación de contenido para las apps de este tipo debe ser intuitiva, visualmente agradable y atractiva.

Los navegadores de catálogos suelen constar de varias secciones, y cada una tiene una lista de contenido multimedia. Entre los ejemplos de secciones de un catálogo de contenido multimedia, se incluyen las playlists, el contenido destacado y las categorías recomendadas.

Figura 1: Pantalla de catálogo típica. Los usuarios pueden explorar los datos del catálogo de videos.

Usa las funciones que proporciona Compose para TV para implementar una interfaz de usuario que permita explorar música o videos del catálogo de contenido multimedia de tu app.

Crea una función de componibilidad para el catálogo

Todo lo que aparece en una pantalla se implementa como una función de componibilidad en Compose para TV. Comienza por definir una función de componibilidad para el navegador del catálogo de contenido multimedia:

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

CatalogBrowser es la función de componibilidad que implementa el navegador de tu catálogo de contenido multimedia. La función toma los siguientes argumentos:

  • Es la lista de contenido destacado.
  • Es la lista de secciones.
  • Un objeto Modifier.
  • Es una función de devolución de llamada que activa una transición de pantalla.

Cómo establecer elementos de IU

Compose para TV ofrece listas diferidas, un componente para mostrar una gran cantidad de elementos (o una lista de longitud desconocida). Llama a LazyColumn para colocar las secciones de forma vertical. LazyColumn proporciona un bloque LazyListScope.() -> Unit, que ofrece un DSL para definir el contenido de los elementos. En el siguiente ejemplo, cada sección se coloca en una lista vertical con un espacio de 16 dp entre las secciones:

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

En el ejemplo, la función de componibilidad SectionRow define cómo mostrar las secciones. En la siguiente función, LazyRow demuestra cómo se usa de manera similar esta versión horizontal de LazyColumn para definir una lista horizontal con un bloque LazyListScope.() -> Unit llamando a la DSL proporcionada:

@Composable
fun SectionRow(
    section: Section,
    modifier: Modifier = Modifier,
    onItemSelected: (Movie) -> Unit = {},
) {
    Text(
        text = section.title,
        style = MaterialTheme.typography.headlineSmall,
    )
    MovieCatalog(
        section.movieList,
        onClick = { movie -> onItemSelected(movie) },
        modifier
    )
}

@Composable
fun MovieCatalog(
    movies: List<Movie>,
    onClick: (Movie) -> Unit,
    modifier: Modifier = Modifier,
) {
    LazyRow(
        modifier = modifier,
        horizontalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        items(movies.size) { index ->
            val movie = movies[index]
            MovieCard(
                movie = movie,
                onClick = { onClick(movie) }
            )
        }
    }
}

En el elemento que admite composición SectionRow, se usa el componente Text. El texto y otros componentes definidos en Material Design se ofrecen en la biblioteca de tv-material . Puedes cambiar el estilo de los textos como se define en Material Design haciendo referencia al objeto MaterialTheme. Este objeto también lo proporciona la biblioteca tv-material. Card forma parte de la biblioteca tv-material. MovieCard define cómo se renderizan los datos de cada película en el catálogo, como se muestra en el siguiente fragmento:

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

En el ejemplo que se describió antes, todas las películas se muestran de la misma manera. Tienen la misma área, no hay diferencia visual entre ellas. Puedes destacar algunos de ellos con Carousel.

El carrusel muestra la información en un conjunto de elementos que se pueden deslizar, atenuar o mover para que se vean. Usa el componente para destacar contenido, como películas nuevas o episodios nuevos de programas de TV.

Carousel espera que, como mínimo, especifiques la cantidad de elementos que tiene el carrusel y cómo dibujar cada uno. El primero se puede especificar con itemCount. El segundo se puede pasar como una expresión lambda. El número de índice del elemento que se muestra se asigna a la lambda. Puedes determinar el elemento que se muestra con el valor de índice dado:

Carousel puede ser un elemento de una lista diferida, como LazyColumn. En el siguiente fragmento, se muestra el elemento FeaturedCarousel componible sobre todos los elementos SectionRow componibles: