テレビで使用するメディアアプリでは、ユーザーが提供コンテンツをブラウズして選び、再生を開始できるようにする必要があります。このタイプのアプリのコンテンツ ブラウジングに関するユーザー エクスペリエンスは、直観的で、目を楽しませる魅力的なものである必要があります。
カタログ ブラウザは通常、複数のセクションで構成され、各セクションにはメディア コンテンツのリストが含まれています。メディア カタログのセクションの例としては、プレイリスト、おすすめコンテンツ、おすすめカテゴリなどがあります。
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 つ目のアイテムはラムダとして渡すことができます。表示されるアイテムのインデックス番号がラムダに渡されます。指定されたインデックス値を使用して、表示されるアイテムを決定できます。
@OptIn(ExperimentalTvMaterial3Api::class) @Composable fun 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.movie_placeholder ), contentScale = ContentScale.Crop, modifier = Modifier.fillMaxSize() ) Text(text = content.title) } } }
Carousel は、LazyColumn などの Lazy リストのアイテムにすることができます。
次のスニペットは、すべての SectionRow コンポーズ可能関数の上にある FeaturedCarousel コンポーズ可能関数を示しています。
@OptIn(ExperimentalTvMaterial3Api::class) @Composable fun CatalogBrowser( featuredContentList: List<Movie>, sectionList: List<Section>, modifier: Modifier = Modifier, onItemSelected: (Movie) -> Unit = {}, ) { LazyColumn( modifier = modifier.fillMaxSize(), verticalArrangement = Arrangement.spacedBy(16.dp) ) { item { FeaturedCarousel(featuredContentList) } items(sectionList) { section -> SectionRow(section, onItemSelected = onItemSelected) } } }