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 xem các nội dung mà ứng dụng cung cấp, chọn nội dung và bắt đầu phát nội dung. Trải nghiệm duyệt xem nội dung của các ứng dụng thuộc loại này phải đơn giản, trực quan, bắt mắt và hấp dẫn.

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

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

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

Tạo một 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 một hàm có khả năng kết hợp trong Compose cho TV. Bắt đầu bằng cách 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:

@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 phần.
  • Một đối tượng Modifier.
  • Một hàm gọi lại, kích hoạt quá trình chuyển đổi màn hình.

Đặt các phần tử trên giao diện người dùng

Compose cho TV cung cấp danh sách tải từng phần, 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). Gọi LazyColumn để đặt các phần theo chiều dọc. LazyColumn cung cấp một khối LazyListScope.() -> 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 16 dp giữa các phần:

@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) { 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, LazyRow minh hoạ cách sử dụng phiên bản ngang này của LazyColumn để xác định một danh sách ngang có khối LazyListScope.() -> 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,
  )
  LazyRow(
     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 dùng. Văn bản và các thành phần khác được xác định trong Material Design có trong thư viện tv-material . Bạn có thể thay đổi kiểu văn bản như được 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. Card là một phần của thư viện tv-material. MovieCard xác định cách hiển thị từng dữ liệu phim trong danh mục được xác định là đoạn mã sau:

@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ụ được mô tả trước đó, tất cả các bộ phim đều được hiển thị như nhau. Chúng có cùng diện tích và không có sự khác biệt về hình ảnh. Bạn có thể làm nổi bật một số phần tử bằng Carousel.

Băng chuyền hiển thị thông tin trong một nhóm các mục có thể trượt, mờ dần hoặc di chuyển vào khung hiển thị. Bạn có thể dùng thành phần này để làm nổi bật nội dung được đề xuấ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 yêu cầu bạn chỉ định ít nhất số lượng mục mà Băng chuyền có và cách vẽ từng mục. Bạn có thể chỉ định phần tử đầu tiên bằng itemCount. Bạn có thể truyền đối số thứ hai dưới dạng một hàm lambda. Số chỉ mục của mục được hiển thị sẽ được cung cấp cho lambda. Bạn có thể xác định mục được hiển thị bằng giá trị chỉ mục đã cho:

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