Um app de música executado em uma TV precisa permitir que os usuários naveguem pelas ofertas de conteúdo, façam uma seleção e iniciem a reprodução. A experiência de navegação de conteúdo para apps desse tipo precisa ser intuitiva, visualmente agradável e envolvente.
Os navegadores de catálogo costumam consistir em várias seções, e cada seção tem uma lista de conteúdo de mídia. Exemplos de seções em um catálogo de mídia incluem: playlists, conteúdo em destaque, categorias recomendadas.
Use as funções fornecidas pelo Compose para TV para implementar uma interface do usuário para navegar por músicas ou vídeos do catálogo de mídia do seu app.
Criar uma função combinável para o catálogo
Tudo o que aparece em uma tela é implementado como uma função combinável no Compose para TV. Comece definindo uma função combinável para o navegador de catálogo de mídia:
@Composable fun CatalogBrowser( featuredContentList: List<Movie>, sectionList: List<Section>, modifier: Modifier = Modifier, onItemSelected: (Movie) -> Unit = {}, ) { // ToDo: add implementation }
CatalogBrowser é a função combinável que implementa o navegador do catálogo de
mídia. A função usa os seguintes argumentos:
- Lista de conteúdo em destaque.
- Lista de seções.
- Um objeto Modifier.
- Uma função de callback, que aciona uma transição de tela.
Definir elementos da IU
O Compose para TV oferece listas lentas, um componente para exibir um grande
número de itens (ou uma lista de tamanho desconhecido). Chame
LazyColumn
para colocar as seções verticalmente. LazyColumn fornece um bloco
LazyListScope.() -> Unit, que oferece uma DSL para definir o conteúdo do item. No exemplo a seguir,
cada seção é colocada em uma lista vertical com um intervalo de 16 dp entre as seções:
@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) } } }
No exemplo, a função combinável SectionRow define como mostrar
seções.
Na função abaixo, LazyRow demonstra como essa
versão horizontal de LazyColumn é usada de maneira semelhante para
definir uma lista horizontal com um bloco LazyListScope.() -> Unit chamando
a DSL fornecida:
@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) } ) } } }
No elemento combinável SectionRow, o componente Text é usado.
O texto e outros componentes
definidos no Material Design são oferecidos na biblioteca tv-material . É possível
mudar o estilo dos textos, conforme definido no Material Design, consultando o
objeto MaterialTheme.
Esse objeto também é fornecido pela biblioteca tv-material.
Card faz parte da biblioteca tv-material.
MovieCard define como cada dado de filme é renderizado no catálogo definido
como o snippet a seguir:
@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, ) } }
Destacar conteúdo em destaque
No exemplo descrito anteriormente, todos os filmes são exibidos da mesma forma.
Eles têm a mesma área, sem diferença visual entre eles.
Você pode destacar alguns deles com Carousel.
O carrossel exibe as informações em um conjunto de itens que podem deslizar, desaparecer ou entrar em exibição. Use o componente para destacar conteúdo em destaque, como filmes recém-disponibilizados ou novos episódios de programas de TV.
Carousel
espera que você especifique pelo menos o número de itens que o carrossel tem e como
desenhar cada item. O primeiro pode ser especificado com itemCount. O segundo
pode ser transmitido como um lambda. O número do índice do item exibido é
fornecido para o lambda. É possível determinar o item exibido com o
valor de índice fornecido:
@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 pode ser um item de uma lista lenta, como LazyColumn.
O snippet a seguir mostra o elemento combinável FeaturedCarousel sobre todos os
elementos combináveis 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) } } }