Tworzenie przeglądarki katalogu

Aplikacja do multimediów uruchamiana na telewizorze musi umożliwiać użytkownikom przeglądanie ofert, wybieranie treści i rozpoczynanie odtwarzania. Przeglądanie treści w tego typu aplikacjach powinno być proste i intuicyjne, a także przyjemne dla oka i wciągające.

W tej sekcji opisujemy, jak używać funkcji dostępnych w funkcji Utwórz na telewizory do implementacji interfejsu do przeglądania muzyki i filmów z katalogu multimediów aplikacji.

Rysunek 1. Typowy ekran katalogu. Użytkownicy mogą przeglądać dane z katalogu filmów.

Przeglądarka katalogu multimediów składa się zwykle 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,

Tworzenie funkcji kompozycyjnej dla katalogu

Wszystko, co znajduje się na ekranie, jest implementowane jako funkcja kompozycyjna w przypadku YouTube TV. Zaczniesz od zdefiniowania funkcji kompozycyjnej dla przeglądarki katalogu multimediów w postaci tego fragmentu kodu:

@Composable
fun CatalogBrowser(
   featuredContentList: List<Movie>,
   sectionList: List<Section>,
   modifier: Modifier = Modifier,
   onItemSelected: (Movie) -> Unit = {},
) {
// ToDo: add implementation
}

CatalogBrowser to funkcja kompozycyjna implementująca przeglądarkę katalogu multimediów. Funkcja przyjmuje te argumenty:

  • Lista polecanych treści.
  • Lista sekcji.
  • Obiekt modyfikatora.
  • Funkcja wywołania zwrotnego, która uruchamia przejście ekranu.

Ustawianie elementów interfejsu

Funkcja tworzenia wiadomości na telewizory udostępnia leniwe listy, czyli komponent służący do wyświetlania dużej liczby elementów (lub list o nieznanej długości). Wywołaj metodę TvLazyColumn, aby umieścić sekcje w pionie. TvLazyColumn udostępnia blok TvLazyListScope.() -> Unit, który umożliwia definiowanie zawartości elementu za pomocą DSL. W poniższym przykładzie każda sekcja jest umieszczona na pionowej liście z odstępem między sekcjami wynoszącym 16 dp.

@Composable
fun CatalogBrowser(
   featuredContentList: List<Movie>,
   sectionList: List<Section>,
   modifier: Modifier = Modifier,
   onItemSelected: (Movie) -> Unit = {},
) {
  TvLazyColumn(
    modifier = modifier.fillMaxSize(),
    verticalArrangement = Arrangement.spacedBy(16.dp)
  ) {
    items(sectionList) { section ->
      Section(section, onItemSelected = onItemSelected)
    }
  }
}

W przykładzie funkcja kompozycyjna Section określa sposób wyświetlania sekcji. W poniższej funkcji TvLazyRow pokazuje, jak ta pozioma wersja TvLazyColumn jest podobnie używana do definiowania poziomej listy z blokiem TvLazyListScope.() -> Unit przez wywołanie podanego DSL.

@Composable
fun Section(
  section: Section,
  modifier: Modifier = Modifier,
  onItemSelected: (Movie) -> Unit = {},
) {
  Text(
    text = section.title,
    style = MaterialTheme.typography.headlineSmall,
  )
  TvLazyRow(
     modifier = modifier,
     horizontalArrangement = Arrangement.spacedBy(8.dp)
  ) {
    items(section.movieList){ movie ->
    MovieCard(
         movie = movie,
         onClick = { onItemSelected(movie) }
       )
    }
  }
}

W komponencie Section używany jest komponent Text. Tekst i inne komponenty zdefiniowane w stylu Material Design są dostępne w bibliotece materiałów tv . Styl tekstu określony w stylu Material Design możesz zmienić, odwołując się do obiektu MaterialTheme. Ten obiekt jest też udostępniany przez bibliotekę tv-material. MovieCard określa sposób renderowania danych każdego filmu w katalogu zdefiniowanym w podanym niżej fragmencie. Card wchodzi też w skład biblioteki materiałów telewizyjnych.

@Composable
fun MovieCard(
   movie: Movie,
   modifier: Modifier = Modifier,
   onClick: () -> Unit = {}
) {
   Card(modifier = modifier, onClick = onClick){
    AsyncImage(
       model = movie.thumbnailUrl,
       contentDescription = movie.title,
     )
   }
}

W przykładzie opisanym wcześniej wszystkie filmy są wyświetlane tak samo. Obejmują one ten sam obszar, nie widać różnic między nimi. Niektóre z nich możesz wyróżnić za pomocą ikony Carousel.

Karuzela wyświetla informacje w formie zbioru elementów, które można przesuwać, zanikać i przesuwać w widoku. Służy on do wyróżniania polecanych treści, takich jak nowo dostępne filmy czy nowe odcinki programów telewizyjnych.

Carousel wymaga co najmniej sprecyzowania liczby elementów w karuzeli oraz sposobu rysowania poszczególnych elementów. Pierwsze można określić za pomocą funkcji itemCount. Drugi można przekazać jako lambda. Funkcja lambda otrzymuje numer indeksu wyświetlanego elementu. Wyświetlany element można określić za pomocą danej wartości indeksu.

@Composable
function 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.placeholder
        ),
        contentScale = ContentScale.Crop,
        modifier = Modifier.fillMaxSize()
      )
      Text(text = content.title)
    }
  }
}

Carousel może być elementem leniwej listy, np. TvLazyColumn. Poniższy fragment kodu pokazuje funkcję FeaturedCarousel kompozycyjną, która znajduje się nad wszystkimi elementami kompozycyjnymi Section.

@Composable
fun CatalogBrowser(
   featuredContentList: List<Movie>,
   sectionList: List<Section>,
   modifier: Modifier = Modifier,
   onItemSelected: (Movie) -> Unit = {},
) {
  TvLazyColumn(
    modifier = modifier.fillMaxSize(),
    verticalArrangement = Arrangement.spacedBy(16.dp)
  ) {

    item {
      FeaturedCarousel(featuredContentList)
    }

    items(sectionList) { section ->
      Section(section, onItemSelected = onItemSelected)
    }
  }
}