カタログ ブラウザを作成する

テレビで使用するメディアアプリでは、ユーザーが提供コンテンツをブラウズして選び、再生を開始できるようにする必要があります。このタイプのアプリのコンテンツ ブラウジングに関するユーザー エクスペリエンスは、直観的で、目を楽しませる魅力的なものである必要があります。

カタログ ブラウザは通常、複数のセクションで構成され、各セクションにはメディア コンテンツのリストが含まれています。メディア カタログのセクションの例としては、プレイリスト、おすすめコンテンツ、おすすめカテゴリなどがあります。

図 1.一般的なカタログ画面。ユーザーは動画カタログデータをブラウジングできます。

Compose for TV で提供される関数を使用して、アプリのメディア カタログから音楽や動画をブラウジングするためのユーザー インターフェースを実装します。

カタログ用のコンポーズ可能な関数を作成する

ディスプレイに表示されるものはすべて、Compose for TV のコンポーズ可能な関数として実装されます。まず、メディア カタログ ブラウザ用のコンポーズ可能な関数を定義します。

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

CatalogBrowser は、メディア カタログ ブラウザを実装するコンポーズ可能な関数です。この関数は次の引数を受け取ります。

  • おすすめコンテンツのリスト。
  • セクションのリスト。
  • Modifier オブジェクト。
  • 画面遷移をトリガーするコールバック関数。

UI 要素を設定する

Compose for TV には、多数のアイテム(または長さが不明なリスト)を表示するコンポーネントである Lazy リストが用意されています。 LazyColumn を呼び出して、セクションを縦方向に配置します。LazyColumn には LazyListScope.() -> Unit ブロックが用意されており、アイテムのコンテンツを定義する DSL を提供します。次の例では、各セクションが縦方向のリストに配置され、セクション間に 16 dp の間隔が設けられています。

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

この例では、SectionRow コンポーズ可能な関数でセクションの表示方法を定義しています。 次の関数では、LazyRow は、 LazyColumn のこの横方向バージョンと同様に LazyListScope.() -> Unit ブロックを使用して 横方向のリストを定義する方法を示しています。

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

SectionRow コンポーズ可能関数では、Text コンポーネントが使用されます。 マテリアル デザインで定義されたテキストやその他のコンポーネントは、tv-material ライブラリで提供されています。`MaterialTheme` オブジェクトを参照することで、マテリアル デザインで定義されているテキストのスタイルを変更できます。このオブジェクトも tv-material ライブラリで提供されています。 Card は tv-material ライブラリの一部です。 MovieCard は、次のスニペットで定義されているカタログで各映画データをレンダリングする方法を定義します。

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

前述の例では、すべての映画が同じように表示されます。 領域は同じで、視覚的な違いはありません。 Carousel を使用して、一部をハイライト表示できます。

カルーセルには、スライド、フェード、またはビューに移動できるアイテムのセットで情報が表示されます。このコンポーネントを使用して、新しく公開された映画やテレビ番組の新しいエピソードなど、注目のコンテンツをハイライト表示します。

Carousel では、カルーセルに表示するアイテムの数と、各アイテムの描画方法を指定する必要があります。最初のアイテムは itemCount で指定できます。2 つ目のアイテムはラムダとして渡すことができます。表示されるアイテムのインデックス番号がラムダに渡されます。指定されたインデックス値を使用して、表示されるアイテムを決定できます。

Carousel は、LazyColumn などの Lazy リストのアイテムにすることができます。 次のスニペットは、すべての SectionRow コンポーズ可能関数の上にある FeaturedCarousel コンポーズ可能関数を示しています。