Aplikacja do multimediów działająca na telewizorze musi umożliwiać użytkownikom przeglądanie oferty treści, wybieranie ich i odtwarzanie. Przeglądanie treści w aplikacjach tego typu powinno być intuicyjne, atrakcyjne wizualnie i angażujące.
Przeglądarki katalogów zwykle składają się z kilku sekcji, a każda z nich zawiera listę treści multimedialnych. Przykłady sekcji w katalogu multimediów: playlisty, polecane treści, polecane kategorie.
Aby zaimplementować interfejs użytkownika do przeglądania muzyki lub filmów z katalogu multimediów aplikacji, użyj funkcji udostępnianych przez Compose na TV.
Tworzenie funkcji typu „composable” dla katalogu
Wszystko, co pojawia się na ekranie, jest implementowane jako funkcja typu „composable” w Compose na TV. Zacznij od zdefiniowania funkcji kompozycyjnej dla przeglądarki katalogu multimediów:
@Composable fun CatalogBrowser( featuredContentList: List<Movie>, sectionList: List<Section>, modifier: Modifier = Modifier, onItemSelected: (Movie) -> Unit = {}, ) { // ToDo: add implementation }
CatalogBrowser to funkcja typu „composable” implementująca przeglądarkę katalogu multimediów. Funkcja przyjmuje te argumenty:
- lista polecanych treści;
- lista sekcji;
- obiekt Modifier;
- funkcja wywołania zwrotnego, która wywołuje przejście do ekranu.
Ustawianie elementów interfejsu
Compose na TV oferuje listy leniwe, czyli komponent do wyświetlania dużej liczby elementów (lub listy o nieznanej długości). Aby umieścić sekcje pionowo, wywołaj
LazyColumn. LazyColumn udostępnia
LazyListScope.() -> Unit
blok, który oferuje DSL do definiowania zawartości elementów. W tym przykładzie każda sekcja jest umieszczana na liście pionowej z odstępem 16 dp między sekcjami:
@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) } } }
W przykładzie funkcja typu „composable” SectionRow określa sposób wyświetlania sekcji.
W tej funkcji LazyRow pokazuje, jak ta
pozioma wersja LazyColumn jest używana w podobny sposób do
definiowania listy poziomej z blokiem LazyListScope.() -> Unit przez wywołanie
podanego DSL:
@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) } ) } } }
W funkcji kompozycyjnej SectionRow używany jest komponent Text.
Tekst i inne komponenty zdefiniowane w Material Design są dostępne w bibliotece tv-material . Możesz
zmienić styl tekstów zdefiniowany w Material Design, odwołując się do
MaterialTheme obiektu.
Ten obiekt jest też udostępniany przez bibliotekę tv-material.
Card jest częścią biblioteki tv-material.
MovieCard określa, jak dane każdego filmu są renderowane w katalogu zdefiniowanym w tym fragmencie kodu:
@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, ) } }
Wyróżnianie polecanych treści
W opisanym wcześniej przykładzie wszystkie filmy są wyświetlane w ten sam sposób.
Zajmują tę samą powierzchnię i nie różnią się wizualnie.
Niektóre z nich możesz wyróżnić za pomocą komponentu Carousel.
Karuzela wyświetla informacje w zestawie elementów, które można przesuwać, przyciemniać lub przenosić do widoku. Używasz tego komponentu do wyróżniania polecanych treści, takich jak nowo dostępne filmy lub nowe odcinki programów telewizyjnych.
Carousel
wymaga podania co najmniej liczby elementów, które ma zawierać, oraz sposobu rysowania każdego elementu. Pierwszy z nich można określić za pomocą itemCount. Drugi można przekazać jako lambdę. Do lambdy przekazywany jest numer indeksu wyświetlanego elementu. Wyświetlany element możesz określić za pomocą podanej wartości indeksu:
@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 może być elementem listy leniwej, np. TvLazyColumn.
Ten fragment kodu pokazuje funkcję kompozycyjną FeaturedCarousel na wszystkich funkcjach kompozycyjnych 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) } } }