Una app de música que se ejecute en una TV debe permitir a los usuarios navegar por los contenidos que ofrece, seleccionarlos y reproducirlos. La experiencia de navegación por el contenido de estas apps debe ser intuitiva, además de visualmente agradable y atractiva.
Los navegadores de catálogos suelen constar de varias secciones, y cada sección tiene una lista de contenido multimedia. Algunos ejemplos de secciones en un catálogo de contenido multimedia incluyen playlists, contenido destacado y categorías recomendadas.
Usa las funciones que proporciona Compose para TV para implementar una interfaz de usuario que permita navegar por música o videos desde el catálogo de medios 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 medios:
@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 del catálogo de medios. La función toma los siguientes argumentos:
- Lista de contenido destacado
- Lista de secciones
- Un objeto Modifier
- 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
LazyColumn
para colocar secciones verticalmente. LazyColumn proporciona un
LazyListScope.() -> Unit
bloque, 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 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 muestra cómo se usa de manera similar esta
versión horizontal de LazyColumn para
definir una lista horizontal con un bloque LazyListScope.() -> Unit llamando
al DSL proporcionado:
@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 componible SectionRow, se usa el componente Text.
El texto y otros componentes definidos en Material Design se ofrecen en la biblioteca tv-material . Puedes
cambiar el estilo de los textos tal como se define en Material Design haciendo referencia al
MaterialTheme objeto.
Esta biblioteca también proporciona este objeto.
Card forma parte de la biblioteca tv-material.
MovieCard define cómo se renderizan los datos de cada película en el catálogo definido como 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, ) } }
Cómo destacar contenido destacado
En el ejemplo descrito anteriormente, todas las películas se muestran por igual.
Tienen la misma área y no hay diferencias visuales entre ellas.
Puedes destacar algunas de ellas con Carousel.
El carrusel muestra la información en un conjunto de elementos que pueden deslizarse, atenuarse o moverse a la vista. Usas el componente para destacar contenido destacado, como películas recién disponibles o episodios nuevos de programas de TV.
Carousel
espera que al menos especifiques la cantidad de elementos que tiene Carousel y cómo dibujar cada elemento. El primero se puede especificar con itemCount. El segundo se puede pasar como una expresión lambda. El número de índice del elemento mostrado se le da a la expresión lambda. Puedes determinar el elemento mostrado con el valor de índice determinado:
@OptIn(ExperimentalTvMaterial3Api::class) @Composable fun 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.movie_placeholder ), contentScale = ContentScale.Crop, modifier = Modifier.fillMaxSize() ) Text(text = content.title) } } }
Carousel puede ser un elemento de una lista diferida, como TvLazyColumn.
En el siguiente fragmento, se muestra el elemento componible FeaturedCarousel sobre todos los elementos componibles SectionRow:
@OptIn(ExperimentalTvMaterial3Api::class) @Composable fun CatalogBrowser( featuredContentList: List<Movie>, sectionList: List<Section>, modifier: Modifier = Modifier, onItemSelected: (Movie) -> Unit = {}, ) { LazyColumn( modifier = modifier.fillMaxSize(), verticalArrangement = Arrangement.spacedBy(16.dp) ) { item { FeaturedCarousel(featuredContentList) } items(sectionList) { section -> SectionRow(section, onItemSelected = onItemSelected) } } }