Une application multimédia exécutée sur un téléviseur doit permettre aux utilisateurs de parcourir ses offres de contenu, d'effectuer une sélection et de lancer la lecture du contenu. L'expérience de navigation dans le contenu pour les applications de ce type doit être intuitive, visuellement agréable et attrayante.
Les navigateurs de catalogue se composent généralement de plusieurs sections, chacune contenant une liste de contenus multimédias. Voici quelques exemples de sections dans un catalogue multimédia : playlists, sélection de contenus, catégories recommandées.
Utilisez les fonctions fournies par Compose pour TV afin d'implémenter une interface utilisateur permettant de parcourir la musique ou les vidéos du catalogue multimédia de votre application.
Créer une fonction composable pour le catalogue
Tout ce qui apparaît sur un écran est implémenté en tant que fonction composable dans Compose pour TV. Commencez par définir une fonction composable pour le navigateur de catalogue multimédia :
@Composable fun CatalogBrowser( featuredContentList: List<Movie>, sectionList: List<Section>, modifier: Modifier = Modifier, onItemSelected: (Movie) -> Unit = {}, ) { // ToDo: add implementation }
CatalogBrowser est la fonction composable qui implémente votre navigateur de catalogue multimédia. La fonction utilise les arguments suivants :
- Liste des contenus mis en avant.
- Liste des sections.
- Objet Modifier.
- Une fonction de rappel, qui déclenche une transition d'écran.
Définir des éléments d'interface utilisateur
Compose pour TV propose des listes "lazy", un composant permettant d'afficher un grand nombre d'éléments (ou une liste d'une longueur indéterminée). Appelez LazyColumn pour placer les sections verticalement. LazyColumn fournit un bloc LazyListScope.() -> Unit, qui propose un DSL pour définir le contenu des éléments. Dans l'exemple suivant, chaque section est placée dans une liste verticale avec un espace de 16 dp entre les sections :
@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) } } }
Dans l'exemple, la fonction composable SectionRow définit comment afficher les sections.
Dans la fonction suivante, LazyRow montre comment cette version horizontale de LazyColumn est utilisée de la même manière pour définir une liste horizontale avec un bloc LazyListScope.() -> Unit en appelant le DSL fourni :
@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) } ) } } }
Dans le composable SectionRow, le composant Text est utilisé.
Le texte et les autres composants définis dans Material Design sont proposés dans la bibliothèque tv-material . Vous pouvez modifier le style des textes tel qu'il est défini dans Material Design en vous référant à l'objet MaterialTheme.
Cet objet est également fourni par la bibliothèque tv-material.
Card fait partie de la bibliothèque tv-material.
MovieCard définit la façon dont les données de chaque film sont affichées dans le catalogue, comme indiqué dans l'extrait suivant :
@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, ) } }
Mettre en avant une sélection de contenus
Dans l'exemple décrit précédemment, tous les films sont affichés de la même manière.
Ils ont la même surface, aucune différence visuelle entre eux.
Vous pouvez en mettre certains en avant avec Carousel.
Le carrousel affiche les informations dans un ensemble d'éléments qui peuvent glisser, s'estomper ou se déplacer dans la vue. Vous utilisez le composant pour mettre en avant une sélection de contenus, tels que des films récemment disponibles ou de nouveaux épisodes de programmes télévisés.
Carousel attend au moins que vous spécifiiez le nombre d'éléments du carrousel et la manière de dessiner chaque élément. Le premier peut être spécifié avec itemCount. Le second peut être transmis en tant que lambda. Le numéro d'index de l'élément affiché est transmis au lambda. Vous pouvez déterminer l'élément affiché avec la valeur d'index donnée :
@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 peut être un élément d'une liste différée, comme LazyColumn.
L'extrait de code suivant montre le composable FeaturedCarousel au-dessus de tous les composables 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) } } }