1. Sebelum memulai
Compose untuk TV adalah framework UI terbaru untuk mengembangkan aplikasi yang berjalan di Android TV. Framework ini mendapatkan semua manfaat Jetpack Compose untuk aplikasi TV sehingga mem-build UI yang indah dan fungsional untuk aplikasi Anda menjadi lebih mudah. Beberapa manfaat khusus Compose untuk TV mencakup hal berikut:
- Fleksibilitas. Compose dapat digunakan untuk membuat jenis UI apa pun, mulai dari tata letak yang sederhana hingga animasi yang kompleks. Komponen dapat langsung difungsikan, tetapi juga dapat disesuaikan dan ditata agar sesuai dengan kebutuhan aplikasi Anda.
- Pengembangan yang disederhanakan dan dipercepat. Compose kompatibel dengan kode yang sudah ada dan memungkinkan developer membuat aplikasi dengan lebih sedikit kode.
- Intuitif: Compose menggunakan sintaksis deklaratif yang membuatnya intuitif untuk mengubah UI Anda, serta melakukan debug, memahami, dan meninjau kode Anda.
Kasus penggunaan umum untuk aplikasi TV adalah konsumsi media. Pengguna menjelajahi katalog konten dan memilih konten yang ingin ditonton. Konten dapat berupa film, acara TV, atau podcast. Setelah pengguna memilih konten, mereka mungkin ingin melihat informasi lebih lanjut tentang konten tersebut, seperti deskripsi singkat, durasi pemutaran, dan nama kreator. Dalam codelab ini, Anda akan mempelajari cara menerapkan layar browser katalog dan layar detail dengan Compose untuk TV.
Prasyarat
- Pengalaman dengan sintaksis Kotlin, termasuk lambda.
- Pengalaman dasar dengan Compose. Jika Anda tidak terbiasa dengan Compose, selesaikan codelab Dasar-dasar Jetpack Compose.
- Pengetahuan dasar tentang composable dan pengubah.
- Salah satu perangkat berikut untuk menjalankan aplikasi contoh:
- Perangkat Android TV
- Perangkat virtual Android dengan profil dalam kategori definisi perangkat TV
Yang Anda bangun
- Aplikasi pemutar video dengan layar browser katalog dan layar detail.
- Layar browser katalog yang menampilkan daftar video yang dapat dipilih pengguna. Tampilannya akan terlihat seperti gambar berikut:

- Layar detail yang menunjukkan metadata video yang dipilih, seperti judul, deskripsi, dan durasi. Tampilannya akan terlihat seperti gambar berikut:

Yang Anda perlukan
- Versi terbaru Android Studio
- Perangkat Android TV atau perangkat virtual dalam kategori perangkat TV
2. Memulai persiapan
Untuk mendapatkan kode yang berisi tema dan penyiapan dasar untuk codelab ini, lakukan salah satu hal berikut:
- Clone kode dari repositori GitHub ini:
$ git clone https://github.com/android/tv-codelabs.git
Cabang main berisi kode awal dan cabang solution berisi kode solusi.
- Download file
main.zip, yang berisi kode awal, dan filesolution.zip, yang berisi kode solusi.
Setelah berhasil mendownload kode, buka folder project IntroductionToComposeForTV di Android Studio. Sekarang Anda siap untuk memulai.
3. Menerapkan layar browser katalog
Layar browser katalog memungkinkan pengguna menjelajahi katalog film. Anda mengimplementasikan browser katalog sebagai fungsi composable. Anda dapat menemukan fungsi composable CatalogBrowser dalam file CatalogBrowser.kt. Anda akan menerapkan layar browser katalog dalam fungsi composable ini.
Kode awal memiliki ViewModel yang disebut class CatalogBrowserViewModel yang memiliki beberapa atribut dan metode untuk mengambil objek Movie yang mendeskripsikan konten film. Anda mengimplementasikan browser katalog dengan objek Movie yang diambil.
CatalogBrowser.kt
@OptIn(ExperimentalTvMaterial3Api::class)
@Composable
fun CatalogBrowser(
modifier: Modifier = Modifier,
catalogBrowserViewModel: CatalogBrowserViewModel = hiltViewModel(),
onMovieSelected: (Movie) -> Unit = {}
) {
}
Menampilkan nama kategori
Anda dapat mengakses daftar kategori dengan atribut catalogBrowserViewModel.categoryList yang merupakan alur daftar Category. Alur ini dikumpulkan sebagai objek Compose State dengan memanggil metode collectAsStateWithLifecycle. Objek Category memiliki atribut name, yang merupakan nilai String yang mewakili nama kategori.
Untuk menampilkan nama kategori, ikuti langkah-langkah berikut:
- Di Android Studio, buka file
CatalogBrowser.ktkode awal, lalu tambahkan fungsi composableLazyColumnke fungsi composableCatalogBrowser. - Panggil metode
catalogBrowserViewModel.categoryList.collectAsStateWithLifeCycle()untuk mengumpulkan alur sebagai objekState. - Deklarasikan
categoryListsebagai properti yang didelegasikan dari objekStateyang Anda buat di langkah sebelumnya. - Panggil fungsi
itemsdengan variabelcategoryListsebagai parameter. - Panggil fungsi composable
Textdengan nama kategori sebagai parameter yang diteruskan sebagai argumen lambda.
CatalogBrowser.kt
@OptIn(ExperimentalTvMaterial3Api::class)
@Composable
fun CatalogBrowser(
modifier: Modifier = Modifier,
catalogBrowserViewModel: CatalogBrowserViewModel = hiltViewModel(),
onMovieSelected: (Movie) -> Unit = {}
) {
val categoryList by catalogBrowserViewModel.categoryList.collectAsStateWithLifecycle()
LazyColumn(modifier = modifier) {
items(categoryList) { category ->
Text(text = category.name)
}
}
}
Menampilkan daftar konten untuk setiap kategori
Objek Category memiliki atribut lain yang disebut movieList. Atribut ini adalah daftar objek Movie yang mewakili film yang termasuk dalam kategori tersebut.
Untuk menampilkan daftar konten untuk setiap kategori, ikuti langkah-langkah berikut:
- Tambahkan fungsi composable
LazyRow, lalu teruskan lambda ke fungsi tersebut. - Di lambda, panggil fungsi
itemsdengancategory.Nilai atributmovieList, lalu teruskan lambda ke nilai tersebut. - Di lambda yang diteruskan ke fungsi
items, panggil fungsi composableMovieCarddengan objekMovie.
CatalogBrowser.kt
@OptIn(ExperimentalTvMaterial3Api::class)
@Composable
fun CatalogBrowser(
modifier: Modifier = Modifier,
catalogBrowserViewModel: CatalogBrowserViewModel = hiltViewModel(),
onMovieSelected: (Movie) -> Unit = {}
) {
val categoryList by
catalogBrowserViewModel.categoryList.collectAsStateWithLifecycle()
LazyColumn(modifier = modifier) {
items(categoryList) { category ->
Text(text = category.name)
LazyRow {
items(category.movieList) {movie ->
MovieCard(movie = movie)
}
}
}
}
}
Opsional: Menyesuaikan tata letak
- Untuk menetapkan jarak antar-kategori, teruskan objek
Arrangementke fungsi composableLazyColumndengan parameterverticalArrangement. ObjekArrangementdibuat dengan memanggil metodeArrangement#spacedBy. - Untuk menetapkan jarak antar-kartu film, teruskan objek
Arrangementke fungsi composableLazyRowdengan parameterhorizontalArrangement. - Untuk menetapkan indentasi ke kolom, teruskan objek
PaddingValuedengan parametercontentPadding.
CatalogBrowser.kt
@OptIn(ExperimentalTvMaterial3Api::class)
@Composable
fun CatalogBrowser(
modifier: Modifier = Modifier,
catalogBrowserViewModel: CatalogBrowserViewModel = hiltViewModel(),
onMovieSelected: (Movie) -> Unit = {}
) {
val categoryList by
catalogBrowserViewModel.categoryList.collectAsStateWithLifeCycle()
LazyColumn(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(16.dp),
contentPadding = PaddingValues(horizontal = 48.dp, vertical = 32.dp)
) {
items(categoryList) { category ->
Text(text = category.name)
LazyRow(
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
items(category.movieList) { movie ->
MovieCard(movie = movie)
}
}
}
}
}
4. Menerapkan layar detail
Layar detail menampilkan detail film yang dipilih. Ada fungsi composable Details dalam file Details.kt. Anda akan menambahkan kode ke fungsi ini untuk menerapkan layar detail.
Details.kt
@Composable
fun Details(movie: Movie, modifier: Modifier = Modifier) {
}
Menampilkan judul film, nama studio, dan deskripsi
Objek Movie memiliki tiga atribut string berikut sebagai metadata film:
title. Judul film.studio. Nama studio yang memproduksi film.description. Ringkasan singkat film.
Untuk menampilkan metadata ini di layar detail, ikuti langkah-langkah berikut:
- Tambahkan fungsi composable
Column, lalu tetapkan jarak vertikal 32 dp dan horizontal 48 dp di sekitar kolom dengan objekModifieryang dibuat oleh metodeModifier.padding. - Tambahkan fungsi composable
Textuntuk menampilkan judul film. - Tambahkan fungsi composable
Textuntuk menampilkan nama studio. - Tambahkan fungsi composable
Textuntuk menampilkan deskripsi film.
Details.kt
@Composable
fun Details(movie: Movie, modifier: Modifier = Modifier) {
Column(
modifier = Modifier
.padding(vertical = 32.dp, horizontal = 48.dp)
) {
Text(text = movie.title)
Text(text = movie.studio)
Text(text = movie.description)
}
}
Objek Modifier yang ditentukan dalam parameter fungsi composable Details digunakan dalam tugas berikutnya.
Menampilkan gambar latar yang terkait dengan objek Movie tertentu
Objek Movie memiliki atribut backgroundImageUrl yang menunjukkan lokasi gambar latar untuk film yang dijelaskan oleh objek.
Agar gambar latar untuk film tertentu dapat ditampilkan, ikuti langkah-langkah berikut:
- Tambahkan fungsi composable
Boxsebagai wrapper fungsi composableColumndengan objekmodifieryang diteruskan melalui fungsi composableDetails. - Dalam fungsi composable
Box, panggil metodefillMaxSizeobjekmodifieruntuk membuat fungsi composableBoxmengisi ukuran maksimum yang dapat dialokasikan ke fungsi composableDetails. - Tambahkan fungsi composable
AsyncImagedengan parameter berikut ke fungsi composableBox:
- Setel nilai atribut
backgroundImageUrldari objekMovieyang diberikan ke parametermodel. - Teruskan
nullke parametercontentDescription.
- Teruskan objek
ContentScale.Cropke parametercontentScale. Untuk melihat opsiContentScaleyang berbeda, lihat Skala konten. - Teruskan nilai return metode
Modifier.fillMaxSizeke parametermodifier.
Details.kt
@Composable
fun Details(movie: Movie, modifier: Modifier = Modifier) {
Box(modifier = modifier.fillMaxSize()) {
AsyncImage(
model = movie.cardImageUrl,
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
)
Column {
Text(
text = movie.title,
)
Text(
text = movie.studio,
)
Text(text = movie.description)
}
}
}
Lihat objek MaterialTheme untuk penerapan tema yang konsisten
Objek MaterialTheme berisi fungsi untuk mereferensikan nilai tema saat ini, seperti yang ada di class Typography dan ColorScheme.
Untuk melihat objek MaterialTheme agar temanya konsisten, ikuti langkah-langkah berikut:
- Tetapkan properti
MaterialTheme.typography.displayMediumke gaya teks judul film. - Setel properti
MaterialTheme.typography.bodySmallke gaya teks dari fungsi composableTextkedua. - Tetapkan properti
MaterialTheme.colorScheme.backgroundke warna latar belakang fungsi composableColumndengan metodeModifier.background.
Details.kt
@Composable
fun Details(movie: Movie, modifier: Modifier = Modifier) {
Box(modifier = modifier.fillMaxSize()) {
AsyncImage(
model = movie.cardImageUrl,
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
)
Column(
modifier = Modifier
.background(MaterialTheme.colorScheme.background),
) {
Text(
text = movie.title,
style = MaterialTheme.typography.displayMedium,
)
Text(
text = movie.studio,
style = MaterialTheme.typography.bodySmall,
)
Text(text = movie.description)
}
}
}
Opsional: Menyesuaikan tata letak
Untuk menyesuaikan tata letak fungsi composable Details, ikuti langkah-langkah berikut:
- Tetapkan fungsi composable
Boxuntuk menggunakan seluruh ruang yang tersedia dengan pengubahfillMaxSize - Tetapkan latar belakang fungsi composable
Boxdengan pengubahbackgrounduntuk mengisi latar belakang dengan gradien linear yang dibuat dengan memanggil fungsiBrush.linearGradientdengan daftar objekColoryang berisi nilaiMaterialTheme.colorScheme.backgrounddanColor.Transparent - Tetapkan jarak horizontal
48.dpdan vertikal24.dpdi sekitar fungsi composableColumndengan Pengubahpadding - Tetapkan dengan fungsi composable
Columndengan pengubahwidthyang dibuat dengan memanggil fungsiModifier.widthdengan nilai0.5f - Tambahkan jarak
8.dpantar fungsi composableTextkedua dan composableTextketiga denganSpacer. Tinggi fungsi composableSpacerditentukan dengan pengubahheightyang dibuat dengan fungsiModifier.height
Details.kt
@Composable
fun Details(movie: Movie, modifier: Modifier = Modifier) {
Box(modifier = modifier.fillMaxSize()) {
AsyncImage(
model = movie.cardImageUrl,
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
)
Box(
modifier = Modifier
.background(
Brush.linearGradient(
listOf(
MaterialTheme.colorScheme.background,
Color.Transparent
)
)
)
.fillMaxSize()
) {
Column(
modifier = Modifier
.padding(horizontal = 48.dp, vertical = 24.dp)
.fillMaxWidth(0.5f)
) {
Text(
text = movie.title,
style = MaterialTheme.typography.displayMedium,
)
Text(
text = movie.studio,
style = MaterialTheme.typography.bodySmall,
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = movie.description,
)
}
}
}
}
5. Menambahkan navigasi antar-layar
Sekarang Anda memiliki browser katalog dan layar detail. Setelah pengguna memilih konten di layar browser katalog, layar harus bertransisi ke layar detail. Untuk memungkinkan hal ini, gunakan pengubah clickable untuk menambahkan pemroses event ke fungsi composable MovieCard. Saat tombol tengah dari tombol arah ditekan, metode CatalogBrowserViewModel#showDetails dipanggil dengan objek film yang terkait dengan fungsi composable MovieCard sebagai argumen.
- Buka file
com.example.tvcomposeintroduction.ui.screens.CatalogBrowser. - Teruskan fungsi lambda ke fungsi composable
MovieCarddengan parameteronClick. - Panggil callback
onMovieSelecteddengan objek film yang terkait dengan fungsi composableMovieCard.
CatalogBrowser.kt
@Composable
fun CatalogBrowser(
modifier: Modifier = Modifier,
catalogBrowserViewModel: CatalogBrowserViewModel = hiltViewModel(),
onMovieSelected: (Movie) -> Unit = {}
) {
val categoryList by
catalogBrowserViewModel.categoryList.collectAsStateWithLifecycle()
LazyColumn(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(16.dp),
contentPadding = PaddingValues(horizontal = 48.dp, vertical = 32.dp)
) {
items(categoryList) { category ->
Text(text = category.name)
LazyRow(
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
items(category.movieList) { movie ->
MovieCard(movie = movie, onClick = { onMovieSelected(movie) })
}
}
}
}
}
6. Menambahkan carousel ke layar browser katalog untuk menandai konten unggulan
Carousel adalah komponen UI yang umum diadaptasikan, yang otomatis mengupdate slide setelah durasi yang ditentukan. Atribut ini biasanya digunakan untuk menyoroti konten unggulan.
Untuk menambahkan carousel ke layar katalog guna menyoroti film dalam daftar konten unggulan, ikuti langkah-langkah berikut:
- Buka file
com.example.tvcomposeintroduction.ui.screens.CatalogBrowser. - Panggil fungsi
itemuntuk menambahkan item ke fungsi composableLazyColumn. - Deklarasikan
featuredMovieListsebagai properti yang didelegasikan dalam lambda yang diteruskan ke fungsiitem, lalu tetapkan objekStateyang akan didelegasikan, yang dikumpulkan dari atributcatalogBrowserViewModel.featuredMovieList. - Panggil fungsi composable
Carouseldi dalam fungsiitem, lalu teruskan parameter berikut:
- Ukuran variabel
featuredMovieListmelalui parameterslideCount. - Objek
Modifieruntuk menentukan ukuran carousel dengan metodeModifier.fillMaxWidthdanModifier.height. Fungsi composableCarouselmenggunakan tinggi 376 dp dengan meneruskan nilai376.dpke metodeModifier.height. - Lambda yang dipanggil dengan nilai bilangan bulat yang menunjukkan indeks item carousel yang terlihat.
- Ambil objek
Moviedari variabelfeaturedMovieListdan nilai indeks yang diberikan. - Tambahkan fungsi composable
Boxke fungsi composableCarousel. - Tambahkan fungsi composable
Textke fungsi composableBoxuntuk menampilkan judul film.
CatalogBrowser.kt
@OptIn(ExperimentalTvMaterial3Api::class)
@Composable
fun CatalogBrowser(
modifier: Modifier = Modifier,
catalogBrowserViewModel: CatalogBrowserViewModel = hiltViewModel(),
onMovieSelected: (Movie) -> Unit = {}
) {
val categoryList by
catalogBrowserViewModel.categoryList.collectAsStateWithLifecycle()
LazyColumn(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(16.dp),
contentPadding = PaddingValues(horizontal = 48.dp, vertical = 32.dp)
) {
item {
val featuredMovieList by catalogBrowserViewModel.featuredMovieList.collectAsStateWithLifecycle()
Carousel(
slideCount = featuredMovieList.size,
modifier = Modifier
.fillMaxWidth()
.height(376.dp)
) { indexOfCarouselSlide ->
val featuredMovie =
featuredMovieList[indexOfCarouselSlide]
Box {
Text(text = featuredMovie.title)
}
}
}
items(categoryList) { category ->
Text(text = category.name)
LazyRow(
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
items(category.movieList) { movie ->
MovieCard(movie = movie, onClick = { onMovieSelected(movie) })
}
}
}
}
}
Menampilkan gambar latar
Fungsi composable Box menempatkan satu komponen di atas komponen lain. Baca Dasar-dasar tata letak untuk mengetahui detail selengkapnya.
Untuk menampilkan gambar latar, ikuti langkah-langkah berikut:
- Panggil fungsi composable
AsyncImageuntuk memuat gambar latar yang terkait dengan objekMoviesebelum fungsi composableText. - Perbarui posisi dan gaya teks fungsi composable
Textuntuk visibilitas yang lebih baik. - Tetapkan placeholder ke fungsi composable
AsyncImageuntuk menghindari pergeseran tata letak. Kode awal memiliki placeholder sebagai drawable yang dapat Anda referensikan denganR.drawable.placeholder.
CatalogBrowser.kt
@OptIn(ExperimentalTvMaterial3Api::class)
@Composable
fun CatalogBrowser(
modifier: Modifier = Modifier,
catalogBrowserViewModel: CatalogBrowserViewModel = hiltViewModel(),
onMovieSelected: (Movie) -> Unit = {}
) {
val categoryList by
catalogBrowserViewModel.categoryList.collectAsStateWithLifecycle()
LazyColumn(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(16.dp),
contentPadding = PaddingValues(horizontal = 48.dp, vertical = 32.dp)
) {
item {
val featuredMovieList by catalogBrowserViewModel.featuredMovieList.collectAsStateWithLifecycle()
Carousel(
slideCount = featuredMovieList.size,
modifier = Modifier
.fillMaxWidth()
.height(376.dp),
) { indexOfCarouselItem ->
val featuredMovie = featuredMovieList[indexOfCarouselItem]
Box{
AsyncImage(
model = featuredMovie.backgroundImageUrl,
contentDescription = null,
placeholder = painterResource(
id = R.drawable.placeholder
),
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize(),
)
Text(text = featuredMovie.title)
}
}
}
items(categoryList) { category ->
Text(text = category.name)
LazyRow(
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
items(category.movieList) { movie ->
MovieCard(movie = movie, onClick = { onMovieSelected(movie) })
}
}
}
}
}
Menambahkan transisi layar ke layar detail
Anda dapat menambahkan Button ke carousel agar pengguna dapat memicu transisi layar ke layar detail dengan mengklik tombol.
Untuk mengizinkan pengguna melihat detail film di carousel yang terlihat di layar detail, ikuti langkah-langkah berikut:
- Panggil fungsi composable
Columndi composableBoxdi composableCarousel - Pindahkan composable
TextdiCarouselke fungsi composableColumn - Panggil fungsi composable
Buttonsetelah fungsi composableTextdi fungsi composableColumn - Panggil fungsi composable
Textdalam fungsi composableButtondengan nilai yang ditampilkan dari fungsistringResourceyang dipanggil denganR.string.show_details. - Panggil fungsi
onMovieSelecteddengan variabelfeaturedMoviedi lambda yang diteruskan ke parameteronClickdari fungsi composableButton
CatalogBrowser.kt
@OptIn(ExperimentalTvMaterial3Api::class)
@Composable
fun CatalogBrowser(
modifier: Modifier = Modifier,
catalogBrowserViewModel: CatalogBrowserViewModel = hiltViewModel(),
onMovieSelected: (Movie) -> Unit = {}
) {
val categoryList by
catalogBrowserViewModel.categoryList.collectAsStateWithLifecycle()
LazyColumn(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(16.dp),
contentPadding = PaddingValues(horizontal = 48.dp, vertical = 32.dp)
) {
item {
val featuredMovieList by catalogBrowserViewModel.featuredMovieList.collectAsStateWithLifecycle()
Carousel(
slideCount = featuredMovieList.size,
modifier = Modifier
.fillMaxWidth()
.height(376.dp),
) { indexOfCarouselItem ->
val featuredMovie = featuredMovieList[indexOfCarouselItem]
Box {
AsyncImage(
model = featuredMovie.backgroundImageUrl,
contentDescription = null,
placeholder = painterResource(
id = R.drawable.placeholder
),
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize(),
)
Column {
Text(text = featuredMovie.title)
Button(onClick = { onMovieSelected(featuredMovie) }) {
Text(text = stringResource(id = R.string.show_details))
}
}
}
}
}
items(categoryList) { category ->
Text(text = category.name)
LazyRow(
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
items(category.movieList) { movie ->
MovieCard(movie = movie, onClick = { onMovieSelected(movie) })
}
}
}
}
}
Opsional: Menyesuaikan tata letak
Untuk menyesuaikan tata letak carousel, ikuti langkah-langkah berikut:
- Tetapkan nilai
backgroundColordengan nilaiMaterialTheme.colorScheme.backgrounddalam fungsi composableCarousel - Gabungkan fungsi composable
Columndengan composableBox - Teruskan nilai
Alignment.BottomStartke parametercontentAlignmentkomponenBox. - Teruskan pengubah
fillMaxSizeke parameter pengubah fungsi composableBox. PengubahfillMaxSizedibuat dengan fungsiModifier.fillMaxSize(). - Panggil metode
drawBehind()di atas pengubahfillMaxSizeyang diteruskan ke composableBox - Di lambda yang diteruskan ke
drawBehindpengubah, tetapkan nilaibrushdengan objekBrushyang dibuat dengan memanggil fungsiBrush.linearGradientdengan daftar dua objekColor. Daftar ini dibuat dengan memanggil fungsilistOfdengan nilaibackgroundColordan nilaiColor.Transparent. - Panggil
drawRectdengan objekbrushdi lambda yang diteruskan ke pengubahdrawBehinduntuk membuat lapisan srim di atas gambar latar - Tentukan padding fungsi composable
Columndengan pengubahpaddingyang dibuat dengan memanggilModifier.paddingdengan nilai20.dp. - Tambahkan fungsi composable
Spacerdengan nilai20.dpantara composableTextdan composableButtondalam fungsi composableColumn
CatalogBrowser.kt
@OptIn(ExperimentalTvMaterial3Api::class)
@Composable
fun CatalogBrowser(
modifier: Modifier = Modifier,
catalogBrowserViewModel: CatalogBrowserViewModel = hiltViewModel(),
onMovieSelected: (Movie) -> Unit = {}
) {
val categoryList by catalogBrowserViewModel.categoryList.collectAsStateWithLifecycle()
LazyColumn(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(32.dp),
contentPadding = PaddingValues(horizontal = 58.dp, vertical = 36.dp)
) {
item {
val featuredMovieList by
catalogBrowserViewModel.featuredMovieList.collectAsStateWithLifecycle()
Carousel(
itemCount = featuredMovieList.size,
modifier = Modifier
.fillMaxWidth()
.height(376.dp),
) { indexOfCarouselItem ->
val featuredMovie = featuredMovieList[indexOfCarouselItem]
val backgroundColor = MaterialTheme.colorScheme.background
Box {
AsyncImage(
model = featuredMovie.backgroundImageUrl,
contentDescription = null,
placeholder = painterResource(
id = R.drawable.placeholder
),
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize(),
)
Box(
contentAlignment = Alignment.BottomStart,
modifier = Modifier
.fillMaxSize()
.drawBehind {
val brush = Brush.horizontalGradient(
listOf(backgroundColor, Color.Transparent)
)
drawRect(brush)
}
) {
Column(
modifier = Modifier.padding(20.dp)
) {
Text(
text = featuredMovie.title,
style = MaterialTheme.typography.displaySmall
)
Spacer(modifier = Modifier.height(28.dp))
Button(onClick = { onMovieSelected(featuredMovie) }) {
Text(text = stringResource(id = R.string.show_details))
}
}
}
}
}
}
items(categoryList) { category ->
Text(text = category.name)
LazyRow(
horizontalArrangement = Arrangement.spacedBy(16.dp),
modifier = Modifier.height(200.dp)
) {
items(category.movieList) { movie ->
MovieCard(
movie,
onClick = {
onMovieSelected(it)
}
)
}
}
}
}
}
7. Mendapatkan kode solusi
Untuk mendownload kode solusi untuk codelab ini, lakukan salah satu hal berikut:
- Klik tombol berikut untuk mendownloadnya sebagai file zip, lalu ekstrak dan buka di Android Studio.
- Ambil dengan Git:
$ git clone https://github.com/android/tv-codelabs.git $ cd tv-codelabs $ git checkout solution $ cd IntroductionToComposeForTV
8. Selamat.
Selamat! Anda telah mempelajari dasar-dasar Compose untuk TV:
- Cara menerapkan layar untuk menampilkan daftar konten dengan menggabungkan LazyColumn dan LazyLow.
- Implementasi layar dasar untuk menampilkan detail konten.
- Cara menambahkan transisi layar antara dua layar.