Aplikacja do multimediów, która działa na telewizorze, musi umożliwiać użytkownikom przeglądanie oferty treści, dokonywanie wyboru i rozpoczynanie odtwarzania. 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.
Użyj funkcji dostępnych w Compose na TV, aby zaimplementować interfejs użytkownika do przeglądania muzyki lub filmów z katalogu multimediów aplikacji.
Tworzenie funkcji typu „composable” dla katalogu
Wszystko, co pojawia się na wyświetlaczu, jest implementowane jako funkcja typu „composable” w Compose na TV. Zacznij od zdefiniowania funkcji typu „composable” 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.
- funkcję wywołania zwrotnego, która aktywuje przejście między ekranami;
Ustawianie elementów interfejsu
Compose na TV oferuje leniwe listy, czyli komponent do wyświetlania dużej liczby elementów (lub listy o nieznanej długości). Wywołaj LazyColumn, aby umieścić sekcje pionowo. LazyColumn udostępnia blok LazyListScope.() -> Unit, który oferuje DSL do definiowania zawartości elementu. W tym przykładzie każda sekcja jest umieszczona 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 tym przykładzie funkcja typu „composable” SectionRow określa, jak wyświetlać sekcje.
W poniższej funkcji LazyRow pokazuje, jak ta pozioma wersja LazyColumn jest używana 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 tekstu zgodnie z definicją w Material Design, odwołując się do obiektu MaterialTheme.
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.
Mają ten sam obszar i nie ma między nimi żadnej różnicy wizualnej.
Możesz wyróżnić niektóre z nich za pomocą Carousel.
Karuzela wyświetla informacje w zestawie elementów, które mogą się przesuwać, zanikać lub pojawiać w widoku. Za pomocą tego komponentu możesz wyróżniać polecane treści, takie jak nowo dostępne filmy lub nowe odcinki programów telewizyjnych.
Carousel wymaga co najmniej określenia liczby elementów w karuzeli i sposobu rysowania każdego z nich. Pierwszy z nich można określić za pomocą itemCount. Drugi można przekazać jako lambdę. Do funkcji lambda przekazywany jest numer indeksu wyświetlanego elementu. Możesz określić wyświetlany element 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. LazyColumn.
Poniższy fragment kodu pokazuje funkcję kompozycyjną FeaturedCarousel nad wszystkimi funkcjami kompozycyjnymi 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) } } }