Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang
Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.
Ứ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:
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, 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:
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:
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:
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 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 tượng 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:
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:
Nội dung và mã mẫu trên trang này phải tuân thủ các giấy phép như mô tả trong phần Giấy phép nội dung. Java và OpenJDK là nhãn hiệu hoặc nhãn hiệu đã đăng ký của Oracle và/hoặc đơn vị liên kết của Oracle.
Cập nhật lần gần đây nhất: 2025-08-21 UTC.
[null,null,["Cập nhật lần gần đây nhất: 2025-08-21 UTC."],[],[],null,["A media app that runs on a TV needs to allow users to browse its content\nofferings, make a selection, and start playing content. The content browsing\nexperience for apps of this type should be simple, intuitive, and visually\npleasing and engaging.\n\nA media catalog browser tends to consist of several sections, and each section\nhas a list of media content. Examples of sections in a media catalog include:\nplaylists, featured content, recommended categories.\n**Figure 1.** Typical catalog screen. Users are able to browse video catalog data.\n\nUse the functions provided by Compose for TV to implement a user\ninterface for browsing music or videos from your app's media catalog.\n\nCreate a composable function for catalog\n\nEverything appearing on a display is implemented as a composable function in\nCompose for TV. Start by defining a composable\nfunction for the media catalog browser: \n\n @Composable\n fun CatalogBrowser(\n featuredContentList: List\u003cMovie\u003e,\n sectionList: List\u003cSection\u003e,\n modifier: Modifier = Modifier,\n onItemSelected: (Movie) -\u003e Unit = {},\n ) {\n // ToDo: add implementation\n }\n\n`CatalogBrowser` is the composable function implementing your media catalog\nbrowser. The function takes the following arguments:\n\n- List of featured content.\n- List of sections.\n- A Modifier object.\n- A callback function, which triggers a screen transition.\n\nSet UI elements\n\nCompose for TV offers lazy lists, a component to display a large\nnumber of items (or a list of an unknown length). Call\n[`LazyColumn`](/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyColumn(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1))\nto place sections vertically. `LazyColumn` provides a\n[`LazyListScope.() -\u003e Unit`](/reference/kotlin/androidx/compose/foundation/lazy/LazyListScope)\nblock, which offers a DSL to define item contents. In the following example,\neach section is placed in a vertical list with a 16 dp gap between sections: \n\n @Composable\n fun CatalogBrowser(\n featuredContentList: List\u003cMovie\u003e,\n sectionList: List\u003cSection\u003e,\n modifier: Modifier = Modifier,\n onItemSelected: (Movie) -\u003e Unit = {},\n ) {\n LazyColumn(\n modifier = modifier.fillMaxSize(),\n verticalArrangement = Arrangement.spacedBy(16.dp)\n ) {\n items(sectionList) { section -\u003e\n Section(section, onItemSelected = onItemSelected)\n }\n }\n }\n\nIn the example, `Section` composable function defines how to display sections.\nIn the following function, [`LazyRow`](/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyRow(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.ui.Alignment.Vertical,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)) demonstrates how this\nhorizontal version of [`LazyColumn`](/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyColumn(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)) is similarly used to\ndefine a horizontal list with a `LazyListScope.() -\u003e Unit` block by calling\nthe provided DSL: \n\n @Composable\n fun Section(\n section: Section,\n modifier: Modifier = Modifier,\n onItemSelected: (Movie) -\u003e Unit = {},\n ) {\n Text(\n text = section.title,\n style = MaterialTheme.typography.headlineSmall,\n )\n LazyRow(\n modifier = modifier,\n horizontalArrangement = Arrangement.spacedBy(8.dp)\n ) {\n items(section.movieList){ movie -\u003e\n MovieCard(\n movie = movie,\n onClick = { onItemSelected(movie) }\n )\n }\n }\n }\n\nIn the `Section` composable, the [`Text`](/reference/kotlin/androidx/tv/material3/package-summary#Text(androidx.compose.ui.text.AnnotatedString,androidx.compose.ui.Modifier,androidx.compose.ui.graphics.Color,androidx.compose.ui.unit.TextUnit,androidx.compose.ui.text.font.FontStyle,androidx.compose.ui.text.font.FontWeight,androidx.compose.ui.text.font.FontFamily,androidx.compose.ui.unit.TextUnit,androidx.compose.ui.text.style.TextDecoration,androidx.compose.ui.text.style.TextAlign,androidx.compose.ui.unit.TextUnit,androidx.compose.ui.text.style.TextOverflow,kotlin.Boolean,kotlin.Int,kotlin.collections.Map,kotlin.Function1,androidx.compose.ui.text.TextStyle)) component is used.\nText and other components\ndefined in Material Design are offered in the tv-material library . You can\nchange the texts' style as defined in Material Design by referring to the\n[`MaterialTheme`](/reference/kotlin/androidx/tv/material3/MaterialTheme) object.\nThis object is also provided by the tv-material library.\n[`Card`](/reference/kotlin/androidx/tv/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,androidx.tv.material3.CardShape,androidx.tv.material3.CardColors,androidx.tv.material3.CardScale,androidx.tv.material3.CardBorder,androidx.tv.material3.CardGlow,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)) is part of the tv-material library.\n`MovieCard` defines how each movie data is rendered in the catalog defined\nas the following snippet: \n\n @Composable\n fun MovieCard(\n movie: Movie,\n modifier: Modifier = Modifier,\n onClick: () -\u003e Unit = {}\n ) {\n Card(modifier = modifier, onClick = onClick){\n AsyncImage(\n model = movie.thumbnailUrl,\n contentDescription = movie.title,\n )\n }\n }\n\n| **Note:** `AsyncImage` is a composable that loads an image from the internet. See [Loading Images](/develop/ui/compose/graphics/images/loading#internet-loading) for details.\n\nHighlight featured content\n\nIn the example described earlier, all movies are displayed equally.\nThey have the same area, no visual difference between them.\nYou can highlight some of them with [`Carousel`](/reference/kotlin/androidx/tv/material3/package-summary#Carousel(kotlin.Int,androidx.compose.ui.Modifier,androidx.tv.material3.CarouselState,kotlin.Long,androidx.compose.animation.ContentTransform,androidx.compose.animation.ContentTransform,kotlin.Function1,kotlin.Function2)).\n\nCarousel displays the information in a set of items that can slide, fade, or\nmove into view. You use the component to highlight featured content, such as\nnewly available movies or new episodes of TV programs.\n\n[`Carousel`](/reference/kotlin/androidx/tv/material3/package-summary#Carousel(kotlin.Int,androidx.compose.ui.Modifier,androidx.tv.material3.CarouselState,kotlin.Long,androidx.compose.animation.ContentTransform,androidx.compose.animation.ContentTransform,kotlin.Function1,kotlin.Function2))\nexpects you to at least specify the number of items that Carousel has and how to\ndraw each item. The first one can be specified with `itemCount`. The second one\ncan be passed as a lambda. The index number of the displayed item is\ngiven to the lambda. You can determine the displayed item with the\ngiven index value: \n\n @Composable\n function FeaturedCarousel(\n featuredContentList: List\u003cMovie\u003e,\n modifier: Modifier = Modifier,\n ) {\n Carousel(\n itemCount = featuredContentList.size,\n modifier = modifier,\n ) { index -\u003e\n val content = featuredContentList[index]\n Box {\n AsyncImage(\n model = content.backgroundImageUrl,\n contentDescription = content.description,\n placeholder = painterResource(\n id = R.drawable.placeholder\n ),\n contentScale = ContentScale.Crop,\n modifier = Modifier.fillMaxSize()\n )\n Text(text = content.title)\n }\n }\n }\n\n`Carousel` can be an item of a lazy list, such as `TvLazyColumn`.\nThe following snippet shows `FeaturedCarousel` composable on top of the\nall `Section` composables: \n\n @Composable\n fun CatalogBrowser(\n featuredContentList: List\u003cMovie\u003e,\n sectionList: List\u003cSection\u003e,\n modifier: Modifier = Modifier,\n onItemSelected: (Movie) -\u003e Unit = {},\n ) {\n TvLazyColumn(\n modifier = modifier.fillMaxSize(),\n verticalArrangement = Arrangement.spacedBy(16.dp)\n ) {\n\n item {\n FeaturedCarousel(featuredContentList)\n }\n\n items(sectionList) { section -\u003e\n Section(section, onItemSelected = onItemSelected)\n }\n }\n }"]]