Katalogbrowser erstellen

Eine Medien-App, die auf einem Fernseher ausgeführt wird, muss Nutzern die Möglichkeit bieten, die verfügbaren Inhalte zu durchsuchen, eine Auswahl zu treffen und Inhalte abzuspielen. Die Suche nach Inhalten für diese Art von Apps sollte einfach und intuitiv sowie visuell ansprechend und ansprechend sein.

In diesem Abschnitt wird beschrieben, wie Sie mit den Funktionen von Compose for TV eine Benutzeroberfläche zum Durchsuchen von Musik oder Videos aus dem Medienkatalog Ihrer App implementieren.

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

Ein Medienkatalog-Browser besteht in der Regel aus mehreren Abschnitten, und jeder Abschnitt enthält eine Liste von Medieninhalten. Beispiele für Bereiche in einem Medienkatalog: Playlists, empfohlene Inhalte, empfohlene Kategorien

Eine zusammensetzbare Funktion für den Katalog erstellen

Alle Elemente, die auf einem Bildschirm angezeigt werden, werden in Composer für Fernseher als zusammensetzbare Funktion implementiert. Zunächst definieren Sie mit dem folgenden Snippet eine zusammensetzbare Funktion für den Medienkatalogbrowser:

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

CatalogBrowser ist die zusammensetzbare Funktion, die den Browser für den Medienkatalog implementiert. Die Funktion verwendet die folgenden Argumente:

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

UI-Elemente festlegen

Mit der Funktion „Compose for TV“ können Sie eine große Anzahl von Elementen (oder eine Liste mit unbekannter Länge) mit Lazy-Listen anzeigen lassen. Sie rufen TvLazyColumn auf, um Bereiche vertikal zu platzieren. TvLazyColumn stellt einen TvLazyListScope.() -> Unit-Block mit einer DSL zur Definition von Elementinhalten bereit. 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 = {},
) {
  TvLazyColumn(
    modifier = modifier.fillMaxSize(),
    verticalArrangement = Arrangement.spacedBy(16.dp)
  ) {
    items(sectionList) { section ->
      Section(section, onItemSelected = onItemSelected)
    }
  }
}

Im Beispiel definiert die zusammensetzbare Funktion Section, wie Abschnitte angezeigt werden. In der folgenden Funktion zeigt TvLazyRow, wie diese horizontale Version von TvLazyColumn in ähnlicher Weise verwendet wird, um eine horizontale Liste mit einem TvLazyListScope.() -> Unit-Block durch Aufrufen der bereitgestellten DSL zu definieren.

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

In der zusammensetzbaren Funktion Section wird die Komponente Text verwendet. Text und andere in Material Design definierte Komponenten werden in der tv-material-Bibliothek angeboten . Sie können den in Material Design definierten Stil des Textes ändern, indem Sie auf das Objekt MaterialTheme verweisen. Dieses Objekt wird auch von der Bibliothek „tv-material“ bereitgestellt. MovieCard definiert, wie die einzelnen Filmdaten im Katalog gerendert werden, der im folgenden Snippet definiert ist. Card gehört auch zur Mediathek „tv-material“.

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

In dem oben beschriebenen Beispiel werden alle Filme gleich angezeigt. Sie haben dieselbe Fläche, keinen visuellen Unterschied zwischen ihnen. Einige davon können Sie mit Carousel hervorheben.

Das Karussell zeigt die Informationen in einer Reihe von Elementen an, die sich verschieben, ausblenden oder in die Ansicht verschieben können. Sie verwenden sie, um Inhalte hervorzuheben, zum Beispiel neue Filme oder Folgen von Fernsehprogrammen.

Für Carousel musst du mindestens die Anzahl der Elemente im Karussell angeben und wissen, wie die einzelnen Elemente gezeichnet werden. Die erste kann mit itemCount angegeben werden. Die zweite kann als Lambda übergeben werden. Die Indexnummer des angezeigten Elements wird der Lambda-Funktion gegeben. Sie können das angezeigte Element anhand des angegebenen Indexwerts 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 List sein, z. B. TvLazyColumn. Das folgende Snippet zeigt die zusammensetzbare Funktion FeaturedCarousel über allen zusammensetzbaren Funktionen von 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)
    }
  }
}