Katalogbrowser erstellen

In einer Media-App, die auf einem Fernseher ausgeführt wird, müssen Nutzer die Inhalte durchsuchen, eine Auswahl treffen und die Wiedergabe starten können. Das Durchsuchen von Inhalten in Apps dieses Typs sollte einfach, intuitiv, visuell ansprechend und interessant sein.

Ein Browser für den Medienkatalog besteht in der Regel aus mehreren Abschnitten, die jeweils eine Liste mit Medieninhalten enthalten. Beispiele für Abschnitte in einem Medienkatalog sind Playlists, vorgestellte Inhalte und empfohlene Kategorien.

Abbildung 1: Typischer Katalogbildschirm. Nutzer können Videokatalogdaten durchsuchen.

Mit den von Compose for TV bereitgestellten Funktionen können Sie eine Benutzeroberfläche zum Durchsuchen von Musik oder Videos aus dem Medienkatalog Ihrer App implementieren.

Zusammensetzbare Funktion für den Katalog erstellen

Alles, was auf einem Display angezeigt wird, ist in Compose for TV als zusammensetzbare Funktion implementiert. Definieren Sie zuerst eine zusammensetzbare Funktion für den Media-Katalogbrowser:

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

CatalogBrowser ist die zusammensetzbare Funktion, die Ihren Media-Katalogbrowser implementiert. Die Funktion verwendet die folgenden Argumente:

  • Liste der empfohlenen Inhalte.
  • Liste der Abschnitte.
  • Ein Modifier-Objekt.
  • Eine Callback-Funktion, die einen Bildschirmübergang auslöst.

UI-Elemente festlegen

Compose for TV bietet Lazy Lists, eine Komponente zum Anzeigen einer großen Anzahl von Elementen (oder einer Liste mit unbekannter Länge). Rufen Sie LazyColumn auf, um Abschnitte vertikal zu platzieren. LazyColumn bietet einen LazyListScope.() -> Unit-Block, der eine DSL zum Definieren von Artikelinhalten bietet. Im folgenden Beispiel wird jeder Abschnitt in einer vertikalen Liste mit einem Abstand von 16 dp zwischen den Abschnitten platziert:

@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) { section ->
      Section(section, onItemSelected = onItemSelected)
    }
  }
}

Im Beispiel wird mit der zusammensetzbaren Funktion Section definiert, wie Abschnitte dargestellt werden. In der folgenden Funktion wird mit LazyRow veranschaulicht, wie diese horizontale Version von LazyColumn ähnlich verwendet wird, um eine horizontale Liste mit einem LazyListScope.() -> Unit-Block zu definieren, indem die bereitgestellte DSL aufgerufen wird:

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

Im zusammensetzbaren Section wird die Komponente Text verwendet. Text und andere in Material Design definierte Komponenten sind in der tv-material-Bibliothek verfügbar . Sie können den Stil der Texte ändern, wie in Material Design definiert, indem Sie auf das Objekt MaterialTheme verweisen. Dieses Objekt wird auch von der tv-material-Bibliothek bereitgestellt. Card ist Teil der Bibliothek für TV-Material. MovieCard definiert, wie die einzelnen Filmdaten im Katalog gerendert werden, der im folgenden Snippet definiert ist:

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

Im oben beschriebenen Beispiel werden alle Filme gleich angezeigt. Sie haben dieselbe Fläche und es gibt keinen visuellen Unterschied zwischen ihnen. Mit Carousel können Sie einige davon hervorheben.

Im Karussell werden die Informationen in einer Reihe von Elementen angezeigt, die eingeblendet, ausgeblendet oder in den Blickpunkt gerückt werden können. Mit der Komponente können Sie ausgewählte Inhalte wie neu verfügbare Filme oder neue Folgen von TV-Sendungen hervorheben.

Bei Carousel müssen Sie mindestens die Anzahl der Elemente im Karussell und die Art und Weise angeben, wie die einzelnen Elemente dargestellt werden sollen. Die erste kann mit itemCount angegeben werden. Die zweite kann als Lambda übergeben werden. Die Indexnummer des angezeigten Elements wird an die Lambda-Funktion übergeben. Sie können das angezeigte Element mit dem angegebenen Indexwert bestimmen:

@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 kann ein Element einer Lazy-Liste sein, z. B. TvLazyColumn. Das folgende Snippet zeigt das FeaturedCarousel-Composable über allen Section-Composables:

@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)
    }
  }
}