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

テレビで動作するメディアアプリでは、ユーザーがコンテンツをブラウジングして選択し、再生を開始できるようにする必要があります。このタイプのアプリのコンテンツ ブラウジング エクスペリエンスは、直感的で、視覚的に魅力的で、魅力的なものである必要があります。

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

図 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 を同様に使用して、提供された DSL を呼び出すことで 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 では、少なくとも、カルーセルに含まれるアイテムの数と、各アイテムの描画方法を指定する必要があります。1 つ目は itemCount で指定できます。2 つ目はラムダとして渡すことができます。表示されたアイテムのインデックス番号がラムダに渡されます。指定されたインデックス値を使用して、表示されるアイテムを決定できます。

Carousel は、LazyColumn などの遅延リストのアイテムにできます。次のスニペットは、すべての SectionRow コンポーザブルの上に FeaturedCarousel コンポーザブルを配置する方法を示しています。