建立目錄瀏覽器

在電視上執行的媒體應用程式,必須讓使用者能瀏覽內容產品、選取項目並開始播放內容。這類應用程式的內容瀏覽體驗應簡單直覺,且兼具視覺美觀和吸引力。

本節將說明如何使用 Compose for TV 提供的函式來實作使用者介面,以便瀏覽應用程式媒體目錄中的音樂或影片。

圖 1. 一般目錄畫面。使用者可以瀏覽影片目錄資料。

媒體目錄瀏覽器通常由數個區段組成,每個區段都有一份媒體內容清單。媒體目錄的版面範例包括:播放清單、精選內容、推薦類別

為目錄建立可組合函式

螢幕上顯示的所有內容都會在 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 提供延遲清單,這個元件可顯示大量項目 (或長度不明的清單)。您將呼叫 TvLazyColumn 以垂直放置區段。TvLazyColumn 提供 TvLazyListScope.() -> Unit 區塊,可提供 DSL 來定義項目內容。在以下範例中,每個區段都會放在垂直清單中,各區段之間的間距為 16 dp。

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

在這個範例中,Section 可組合函式會定義區段顯示方式。在下列函式中,TvLazyRow 示範 TvLazyColumn 的水平版本,如何透過呼叫提供的 DSL,以類似的方式定義具有 TvLazyListScope.() -> Unit 區塊的水平清單。

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

Section 可組合項中,系統會使用 Text 元件。Material Design 中定義的文字和其他元件可在 tv-material 程式庫中取得。您可以藉由參照 MaterialTheme 物件來變更 Material Design 中定義的文字樣式。這個物件也是由 tv-material 程式庫提供。MovieCard 會定義目錄內各項電影資料算繪的方式,如以下程式碼片段所示。Card 也屬於 tv-material 程式庫的一部分。

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

在上述範例中,所有電影的顯示方式均相等。兩者的區域相同,而且兩者沒有任何視覺差異。你可以使用 Carousel 醒目顯示部分項目。

輪轉介面會顯示一組項目中的資訊,這些項目可以滑動、淡出或移至檢視畫面中。使用這個元件可主打精選內容,例如新上架的電影或新上架的電視節目。

Carousel 預期您至少會指定 Carousel 包含的項目數量,以及如何繪製每個項目。第一個可以使用 itemCount 指定。第二種方法能以 lambda 形式傳遞。顯示項目的索引號碼會提供給 lambda。您可以使用指定的索引值來判斷顯示的項目。

@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 可以是 Lazy 清單的項目,例如 TvLazyColumn。下列程式碼片段顯示所有 Section 可組合項頂端的 FeaturedCarousel 可組合項。

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