1. 事前準備
Compose for TV 是最新的 UI 架構,用於開發在 Android TV 上執行的應用程式。此架構可享有適用於 TV 應用程式的 Jetpack Compose 所有優勢,更輕鬆地為應用程式建構美觀且實用的使用者介面。Compose for TV 的一些特定優點如下:
- 高度彈性。Compose 可用於建立任何類型的 UI,從簡單的版面配置到複雜的動畫都沒問題。元件可立即使用,但也可以配合應用程式需求自訂及設定樣式。
- 簡化及加速開發作業。Compose 與現有程式碼相容,且可讓開發人員用較少的程式碼建構應用程式。
- 操作直覺:Compose 採用宣告式語法,讓使用者以符合直覺的方式變更使用者介面,以及偵錯、解讀和檢查程式碼。
電視應用程式的常見用途是使用媒體。使用者瀏覽內容目錄,然後選取要觀看的內容。內容可以是電影、電視節目或 Podcast。使用者選取內容後,可能會想查看更多內容資訊,例如簡短說明、播放長度和創作者名稱。在本程式碼研究室中,您可以學到如何使用 Compose for TV 實作目錄瀏覽器畫面和詳細資料畫面。
必要條件
- 具備 Kotlin 語法經驗 (包括 lambda)。
- 具備 Compose 的基本經驗。如果您不熟悉 Compose,請先完成「Jetpack Compose 基本概念」程式碼研究室。
- 具備可組合函式和修飾符的基本知識。
- 使用下列任一裝置執行範例應用程式:
- Android TV 裝置
- 在電視裝置定義類別中含有設定檔的Android 虛擬裝置
建構內容
- 包含目錄瀏覽器畫面和詳細資料畫面的影片播放器應用程式。
- 目錄瀏覽器畫面,顯示使用者可選擇的影片清單。如下圖所示:
- 詳細資料畫面,顯示所選影片的中繼資料,例如標題、說明和長度。如下圖所示:
需求條件
- 最新版 Android Studio
- Android TV 裝置或電視裝置類別中的虛擬裝置
2. 做好準備
如要取得含有本程式碼研究室的主題設定和基本設定程式碼,請執行下列任一操作:
- 複製這個 GitHub 存放區中的程式碼:
$ git clone https://github.com/android/tv-codelabs.git
main
分支版本含有範例程式碼,solution
分支版本則包含解決方案程式碼。
- 下載含有範例程式碼的
main.zip
檔案,以及包含解決方案程式碼的solution.zip
檔案。
下載程式碼後,請在 Android Studio 中開啟「IntroductionToComposeForTV」專案資料夾。您已完成開始本研究室的準備。
3. 實作目錄瀏覽器畫面
目錄瀏覽器畫面可讓使用者瀏覽電影目錄。您要將目錄瀏覽器實作為可組合函式。您可以在 CatalogBrowser.kt
檔案中找到 CatalogBrowser
可組合函式。您會在這個可組合函式中實作目錄瀏覽器畫面。
範例程式碼含有稱為 CatalogBrowserViewModel
類別的 ViewModel,其中包含幾種屬性和方法,用於擷取描述電影內容的 Movie
物件。您要使用擷取的 Movie
物件實作目錄瀏覽器。
CatalogBrowser.kt
@OptIn(ExperimentalTvMaterial3Api::class)
@Composable
fun CatalogBrowser(
modifier: Modifier = Modifier,
catalogBrowserViewModel: CatalogBrowserViewModel = hiltViewModel(),
onMovieSelected: (Movie) -> Unit = {}
) {
}
顯示類別名稱
您可以使用 catalogBrowserViewModel.categoryList
屬性 (即 Category
清單的資料流) 存取類別清單。系統會透過呼叫資料流的 collectAsStateWithLifecycle
方法,將資料流收集為 Compose State
物件。Category
物件包含 name
屬性,是代表類別名稱的 String
值。
如要顯示類別名稱,請按照下列步驟操作:
- 在 Android Studio 中開啟範例程式碼的
CatalogBrowser.kt
檔案,然後將LazyColumn
可組合函式新增至CatalogBrowser
可組合函式。 - 呼叫
catalogBrowserViewModel.categoryList.collectAsStateWithLifeCycle()
方法,將資料流收集為State
物件。 - 將
categoryList
宣告為您在上一個步驟中所建立State
物件的委派屬性。 - 使用
categoryList
變數做為參數來呼叫items
函式。 - 使用類別名稱做為參數來呼叫
Text
可組合函式,該參數會做為 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)
}
}
}
顯示每個類別的內容清單
Category
物件還有另一個名為 movieList
的屬性。該屬性是 Movie
物件清單,代表屬於該類別的電影。
如要顯示各個類別的內容清單,請按照下列步驟操作:
- 新增
LazyRow
可組合函式,然後將 lambda 傳遞至該函式。 - 在 lambda 中,使用
category
.movieList
屬性值呼叫items
函式,然後將 lambda 傳遞至該函式。 - 在傳遞至
items
函式的 lambda 中,使用Movie
物件呼叫MovieCard
可組合函式。
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)
}
}
}
}
}
選用:調整版面配置
- 如要設定類別之間的間距,請使用
verticalArrangement
參數將Arrangement
物件傳遞至LazyColumn
可組合函式。請透過呼叫Arrangement#spacedBy
方法來建立Arrangement
物件。 - 如要設定電影資訊卡之間的間距,請使用
horizontalArrangement
參數將Arrangement
物件傳遞至LazyRow
可組合函式。 - 若要為資料欄設定縮排,請使用
contentPadding
參數傳遞PaddingValue
物件。
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. 實作詳細資料畫面
詳細資料畫面會顯示所選電影的詳細資料。Details.kt
檔案中有 Details
可組合函式。請將程式碼新增至這個函式,以實作詳細資料畫面。
Details.kt
@Composable
fun Details(movie: Movie, modifier: Modifier = Modifier) {
}
顯示電影名稱、電影公司名稱和說明
Movie
物件包含下列三個字串屬性,做為電影的中繼資料:
title
:電影名稱。studio
:製作電影的公司名稱。description
:電影的簡短摘要。
如要在詳細資料畫面上顯示這項中繼資料,請按照下列步驟操作:
- 新增
Column
可組合函式,然後使用由Modifier.padding
方法建立的Modifier
物件,將資料欄周圍的垂直間距設為 32 dp,水平間距設為 48 dp。 - 新增
Text
可組合函式以顯示電影標題。 - 新增
Text
可組合函式以顯示電影公司名稱。 - 新增
Text
可組合函式以顯示電影說明。
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)
}
}
在 Details
可組合函式的參數中指定的 Modifier
物件,會在下一個工作中用到。
顯示與指定 Movie
「物件」相關聯的背景圖片
Movie
物件包含 backgroundImageUrl
屬性,表示物件所描述電影的背景圖片位置。
如要顯示特定電影的背景圖片,請按照下列步驟操作:
- 新增
Box
可組合函式做為Column
可組合函式的包裝函式,其中modifier
物件是透過Details
可組合函式傳遞。 - 在
Box
可組合函式中,呼叫modifier
物件的fillMaxSize
方法,讓Box
可組合函式填入可分配至Details
可組合函式的大小上限。 - 將含有下列參數的
AsyncImage
可組合函式新增至Box
可組合函式:
- 將指定
Movie
物件的backgroundImageUrl
屬性值設為model
參數。 - 將
null
傳遞至contentDescription
參數。
- 將
ContentScale.Crop
物件傳遞至contentScale
參數。如要查看不同的ContentScale
選項,請參閱「內容縮放」。 - 將
Modifier.fillMaxSize
方法的傳回值傳遞至modifier
參數。
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)
}
}
}
參照 MaterialTheme
物件,讓主題設定保持一致
MaterialTheme
物件含有用於參照目前主題值的函式,例如 Typography
和 ColorScheme
類別中的值。
如要參照 MaterialTheme
物件以讓主題設定保持一致,請按照下列步驟操作:
- 將
MaterialTheme.typography.displayMedium
屬性設為電影標題的文字樣式。 - 將
MaterialTheme.typography.bodySmall
屬性設為第二個Text
可組合函式的文字樣式。 - 使用
Modifier.background
方法,將MaterialTheme.colorScheme.background
屬性設為Column
可組合函式的背景顏色。
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)
}
}
}
選用:調整版面配置
如要調整 Details
可組合函式的版面配置,請按照下列步驟操作:
- 設定
Box
可組合函式,透過fillMaxSize
修飾符使用完整的可用空間 - 使用
background
修飾符設定Box
可組合函式的背景,以便用呼叫Brush.linearGradient
函式 (其中含有包含MaterialTheme.colorScheme.background
和Color.Transparent
的Color
物件清單) 所建立的線性漸層填入背景 - 使用
padding
修飾符,在Column
可組合函式周圍設定48.dp
水平和24.dp
垂直間距 - 使用
width
修飾符 (以0.5f
值呼叫Modifier.width
函式所建立) 設定Column
可組合函式的寬度 - 在第二個
Text
可組合函式和第三個Text
可組合函式之間,使用Spacer
新增8.dp
空間。Spacer
可組合函式的高度,是透過Modifier.height
函式建立的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. 在畫面之間新增導覽
現在您已擁有目錄瀏覽器畫面和詳細資料畫面。使用者在目錄瀏覽器畫面中選取內容後,該畫面就必須轉換為詳細資料畫面。為此,請使用 clickable
修飾符在 MovieCard
可組合函式中加入 event
事件監聽器。當使用者按下方向鍵中間的按鈕時,請使用與 MovieCard
可組合函式相關聯的電影物件做為引數來呼叫 CatalogBrowserViewModel#showDetails
方法。
- 開啟
com.example.tvcomposeintroduction.ui.screens.CatalogBrowser
檔案。 - 使用
onClick
參數將 lambda 函式傳遞至MovieCard
可組合函式。 - 使用與
MovieCard
可組合函式相關聯的電影物件呼叫onMovieSelected
回呼。
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. 將輪轉介面加入目錄瀏覽器畫面,藉此凸顯精選內容
輪轉介面是一種常見的自動調整式 UI 元件,會在指定的時間長度過後自動更新介面的投影片,通常用來凸顯精選內容。
如要在目錄瀏覽器畫面中新增輪轉介面,藉此凸顯精選內容清單中的電影,請按照下列步驟操作:
- 開啟
com.example.tvcomposeintroduction.ui.screens.CatalogBrowser
檔案。 - 呼叫
item
函式,將項目新增至LazyColumn
可組合函式。 - 在傳遞至
item
函式的 lambda 中宣告featuredMovieList
做為委派屬性,然後將State
物件 (從catalogBrowserViewModel.featuredMovieList
屬性收集而來) 設為委派項目。 - 在
item
函式中呼叫Carousel
可組合函式,然後傳入下列參數:
- 透過
slideCount
參數設定featuredMovieList
變數的大小。 Modifier
物件,用於透過Modifier.fillMaxWidth
和Modifier.height
方法指定輪轉介面的大小。Carousel
可組合函式會藉由將376.dp
值傳遞至Modifier.height
方法,將高度設為 376 dp。- 透過整數值呼叫的 lambda,代表可見輪轉介面項目的索引。
- 從
featuredMovieList
變數和指定的索引值擷取Movie
物件。 - 將
Box
可組合函式新增至Carousel
可組合函式。 - 在
Box
可組合函式中新增Text
可組合函式,即可顯示電影標題。
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) })
}
}
}
}
}
顯示背景圖片
Box
可組合函式會將一個元件放在另一個元件上。詳情請參閱「版面配置基本概念」一文。
如要顯示背景圖片,請按照下列步驟操作:
- 呼叫
AsyncImage
可組合函式,在Text
可組合函式之前載入與Movie
物件相關聯的背景圖片。 - 更新
Text
可組合函式的位置和文字樣式,讓畫面更加清楚。 - 將預留位置設為
AsyncImage
可組合函式,以免版面配置位移。範例程式碼含有預留位置做為可繪項目,您可以使用R.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) })
}
}
}
}
}
在詳細資料畫面中新增畫面轉場
您可以在輪轉介面中新增 Button
,讓使用者點選按鈕觸發畫面轉換,前往到詳細資料畫面。
如要讓使用者在詳細資料畫面上,查看可見輪轉介面中的電影詳細資料,請按照下列步驟操作:
- 在
Carousel
可組合函式的Box
可組合函式中呼叫Column
可組合函式 - 將
Carousel
中的Text
可組合函式移至Column
可組合函式 - 在
Column
可組合函式的Text
可組合函式後方呼叫Button
可組合函式 - 在
Button
可組合函式中,使用R.string.show_details
呼叫的stringResource
函式傳回值來呼叫Text
可組合函式。 - 在傳遞至
Button
可組合函式的onClick
參數的 lambda 中使用featuredMovie
變數呼叫onMovieSelected
函式
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) })
}
}
}
}
}
選用:調整版面配置
如要調整輪轉介面的版面配置,請按照下列步驟操作:
- 在
Carousel
可組合函式中,以MaterialTheme.colorScheme.background
值指派backgroundColor
值 - 使用
Box
可組合函式納入Column
可組合函式 - 將
Alignment.BottomStart
值傳遞至Box
元件的contentAlignment
參數。 - 將
fillMaxSize
修飾符傳遞至Box
可組合函式的修飾符參數。fillMaxSize
修飾符是以Modifier.fillMaxSize()
函式建立。 - 透過傳遞至
Box
可組合函式的fillMaxSize
修飾符呼叫drawBehind()
方法 - 在傳遞至
drawBehind
修飾符的 lambda 中,以Brush
物件 (透過呼叫含有兩個Color
物件的清單的Brush.linearGradient
函式所建立) 指派brush
值。清單是透過呼叫含有backgroundColor
值和Color.Transparent
值的listOf
函式所建立。 - 在傳遞至
drawBehind
修飾符的 lambda 中使用brush
物件呼叫drawRect
,藉此在背景圖片上建立 Srim 層 - 使用透過呼叫含有
20.dp
值的Modifier.padding
所建立的padding
修飾符,指定Column
可組合函式的邊框間距。 - 在
Column
可組合函式的Text
可組合函式和Button
可組合函式之間,新增含有20.dp
值的Spacer
可組合函式
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. 取得解決方案程式碼
如要下載本程式碼研究室的解決方案程式碼,請執行下列任一操作:
- 點選下方按鈕即可將其下載為 ZIP 檔案,然後解壓縮並在 Android Studio 中開啟。
- 使用 Git 擷取檔案:
$ git clone https://github.com/android/tv-codelabs.git $ cd tv-codelabs $ git checkout solution $ cd IntroductionToComposeForTV
8. 恭喜。
恭喜!您已瞭解 Compose for TV 的基本概念:
- 如何透過結合 LazyColumn 和 LazyLow,實作顯示內容清單的螢幕畫面。
- 實作顯示內容詳細資料的基本畫面。
- 如何在兩個畫面之間新增畫面轉場。