Tạo trình duyệt danh mục

Ứng dụng đa phương tiện chạy trên TV cần cho phép người dùng duyệt qua các nội dung được cung cấp, lựa chọn và bắt đầu phát nội dung. Trải nghiệm duyệt nội dung cho các ứng dụng thuộc loại này sẽ đơn giản và trực quan, đẹp mắt và hấp dẫn.

Phần này mô tả cách sử dụng các chức năng do Compose dành cho TV cung cấp để triển khai giao diện người dùng để duyệt nhạc hoặc video từ danh mục nội dung nghe nhìn của ứng dụng.

Hình 1. Màn hình danh mục điển hình. Người dùng có thể duyệt xem dữ liệu danh mục video.

Trình duyệt danh mục nội dung đa phương tiện thường bao gồm nhiều phần, và mỗi phần có một danh sách nội dung đa phương tiện. Ví dụ về các phần trong danh mục nội dung nghe nhìn bao gồm: danh sách phát, nội dung nổi bật, danh mục được đề xuất

Tạo hàm có khả năng kết hợp cho danh mục

Mọi thứ xuất hiện trên màn hình đều được triển khai dưới dạng hàm có khả năng kết hợp trong Compose cho TV. Bạn sẽ bắt đầu bằng việc xác định một hàm có khả năng kết hợp cho trình duyệt danh mục nội dung nghe nhìn như đoạn mã sau:

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

CatalogBrowser là hàm có khả năng kết hợp triển khai trình duyệt danh mục nội dung nghe nhìn. Hàm này nhận các đối số sau:

  • Danh sách nội dung nổi bật.
  • Danh sách các mục.
  • Đối tượng Đối tượng sửa đổi.
  • Một hàm callback, kích hoạt quá trình chuyển đổi màn hình.

Thiết lập thành phần trên giao diện người dùng

Compose dành cho TV cung cấp danh sách tải từng phần (lazy danh sách), một thành phần để hiển thị một số lượng lớn các mục (hoặc một danh sách có độ dài không xác định). Bạn sẽ gọi TvLazyColumn để đặt các phần theo chiều dọc. TvLazyColumn cung cấp một khối TvLazyListScope.() -> Unit. Khối này cung cấp một DSL để xác định nội dung của mục. Trong ví dụ sau, mỗi phần được đặt trong một danh sách dọc với khoảng cách giữa các phần là 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)
    }
  }
}

Trong ví dụ này, hàm có khả năng kết hợp Section xác định cách hiển thị các phần. Trong hàm sau, TvLazyRow minh hoạ cách sử dụng phiên bản ngang của TvLazyColumn theo cách tương tự để xác định danh sách theo chiều ngang có khối TvLazyListScope.() -> Unit bằng cách gọi DSL được cung cấp.

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

Trong thành phần kết hợp Section, thành phần Text được sử dụng. Văn bản và các thành phần khác được xác định trong Material Design được cung cấp trong thư viện tv-material . Bạn có thể thay đổi kiểu văn bản như đã xác định trong Material Design bằng cách tham chiếu đến đối tượng MaterialTheme. Đối tượng này cũng do thư viện tv-material cung cấp. MovieCard xác định cách hiển thị từng dữ liệu phim trong danh mục được xác định như đoạn mã sau. Card cũng là một phần của thư viện tv-material.

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

Trong ví dụ mô tả trước đó, tất cả phim được hiển thị như nhau. Chúng có cùng một khu vực, không có sự khác biệt về thị giác. Bạn có thể làm nổi bật một vài trong số đó bằng Carousel.

Băng chuyền hiển thị thông tin trong một tập hợp các mục có thể trượt, làm mờ hoặc di chuyển vào khung hiển thị. Bạn sử dụng thành phần này để làm nổi bật nội dung nổi bật, chẳng hạn như phim mới phát hành hoặc tập mới của chương trình truyền hình.

Carousel mong muốn ít nhất bạn chỉ định số lượng mục trong Băng chuyền và cách vẽ từng mục. Bạn có thể chỉ định thuộc tính đầu tiên bằng itemCount. Biến thứ hai có thể được truyền dưới dạng lambda. Số chỉ mục của mục hiển thị sẽ được gán cho lambda. Bạn có thể xác định mục hiển thị bằng giá trị chỉ mục nhất định.

@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 có thể là một mục trong danh sách tải từng phần, chẳng hạn như TvLazyColumn. Đoạn mã sau đây cho thấy thành phần kết hợp FeaturedCarousel ở trên cùng của tất cả các thành phần kết hợp 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)
    }
  }
}