提供資訊卡檢視模式
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
使用 Compose 建構更優質的內容
使用 Jetpack Compose for Android TV OS 以最少的程式碼建立精美的 UI。
在上一堂課中,您在瀏覽片段中實作了目錄瀏覽器,
會顯示媒體項目清單在本課程中,您將為媒體項目建立資訊卡檢視畫面
顯示在瀏覽片段中
BaseCardView
類別和子類別會顯示與媒體項目相關聯的中繼資料。
ImageCardView
本課程中使用的類別會顯示內容圖片以及媒體項目標題。
另請參閱
Leanback 範例應用程式
,直接在 Google Cloud 控制台實際操作。
圖 1. Leanback 範例應用程式圖片資訊卡檢視畫面 (處於選取狀態)。
建立資訊卡顯示器
Presenter
會產生檢視畫面,並將物件繫結至這些檢視區塊
隨選。在應用程式向使用者顯示內容的瀏覽片段中,您會建立一個
內容資訊卡的 Presenter
,並傳遞至轉接程式
可將內容加入畫面上在下列程式碼中,CardPresenter
建立了
在 onLoadFinished()
LoaderManager
的回呼:
Kotlin
override fun onLoadFinished(loader: Loader<HashMap<String, List<Movie>>>, data: HashMap<String, List<Movie>>) {
rowsAdapter = ArrayObjectAdapter(ListRowPresenter())
val cardPresenter = CardPresenter()
var i = 0L
data.entries.forEach { entry ->
val listRowAdapter = ArrayObjectAdapter(cardPresenter).apply {
entry.value.forEach { movie ->
add(movie)
}
}
val header = HeaderItem(i, entry.key)
i++
rowsAdapter.add(ListRow(header, listRowAdapter))
}
val gridHeader = HeaderItem(i, getString(R.string.more_samples))
val gridRowAdapter = ArrayObjectAdapter(GridItemPresenter()).apply {
add(getString(R.string.grid_view))
add(getString(R.string.error_fragment))
add(getString(R.string.personal_settings))
}
rowsAdapter.add(ListRow(gridHeader, gridRowAdapter))
adapter = rowsAdapter
updateRecommendations()
}
Java
@Override
public void onLoadFinished(Loader<HashMap<String, List<Movie>>> arg0,
HashMap<String, List<Movie>> data) {
rowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
CardPresenter cardPresenter = new CardPresenter();
int i = 0;
for (Map.Entry<String, List<Movie>> entry : data.entrySet()) {
ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);
List<Movie> list = entry.getValue();
for (int j = 0; j < list.size(); j++) {
listRowAdapter.add(list.get(j));
}
HeaderItem header = new HeaderItem(i, entry.getKey());
i++;
rowsAdapter.add(new ListRow(header, listRowAdapter));
}
HeaderItem gridHeader = new HeaderItem(i, getString(R.string.more_samples));
GridItemPresenter gridPresenter = new GridItemPresenter();
ArrayObjectAdapter gridRowAdapter = new ArrayObjectAdapter(gridPresenter);
gridRowAdapter.add(getString(R.string.grid_view));
gridRowAdapter.add(getString(R.string.error_fragment));
gridRowAdapter.add(getString(R.string.personal_settings));
rowsAdapter.add(new ListRow(gridHeader, gridRowAdapter));
setAdapter(rowsAdapter);
updateRecommendations();
}
建立資訊卡檢視模式
在這個步驟中,您會建構卡片顯示器,其中包含用於說明卡片檢視畫面的檢視畫面保留項
媒體內容項目請注意,每位簡報者只能建立一個檢視畫面類型。如果你有兩個
資訊卡檢視類型,則需要兩名資訊卡顯示器。
在 Presenter
中,實作
onCreateViewHolder()
可建立可用於顯示內容項目的檢視容器的回呼:
Kotlin
private const val CARD_WIDTH = 313
private const val CARD_HEIGHT = 176
class CardPresenter : Presenter() {
private lateinit var mContext: Context
private lateinit var defaultCardImage: Drawable
override fun onCreateViewHolder(parent: ViewGroup): Presenter.ViewHolder {
mContext = parent.context
defaultCardImage = mContext.resources.getDrawable(R.drawable.movie)
...
Java
@Override
public class CardPresenter extends Presenter {
private Context context;
private static int CARD_WIDTH = 313;
private static int CARD_HEIGHT = 176;
private Drawable defaultCardImage;
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent) {
context = parent.getContext();
defaultCardImage = context.getResources().getDrawable(R.drawable.movie);
...
在 onCreateViewHolder()
方法中,
可為內容項目建立資訊卡檢視模式以下範例使用
ImageCardView
。
選取資訊卡後,預設行為會將其展開為放大版。如果要指定
所選資訊卡的顏色不同,呼叫 setSelected()
如下所示:
Kotlin
...
val cardView = object : ImageCardView(context) {
override fun setSelected(selected: Boolean) {
val selected_background = context.resources.getColor(R.color.detail_background)
val default_background = context.resources.getColor(R.color.default_background)
val color = if (selected) selected_background else default_background
findViewById<View>(R.id.info_field).setBackgroundColor(color)
super.setSelected(selected)
}
}
...
Java
...
ImageCardView cardView = new ImageCardView(context) {
@Override
public void setSelected(boolean selected) {
int selected_background = context.getResources().getColor(R.color.detail_background);
int default_background = context.getResources().getColor(R.color.default_background);
int color = selected ? selected_background : default_background;
findViewById(R.id.info_field).setBackgroundColor(color);
super.setSelected(selected);
}
};
...
使用者開啟應用程式時,Presenter.ViewHolder
會顯示內容項目的 CardView
物件。您必須先完成相關設定
呼叫 setFocusable(true)
即可從 D-Pad 控制器存取焦點
和setFocusableInTouchMode(true)
,
如以下程式碼所示:
Kotlin
...
cardView.isFocusable = true
cardView.isFocusableInTouchMode = true
return ViewHolder(cardView)
}
Java
...
cardView.setFocusable(true);
cardView.setFocusableInTouchMode(true);
return new ViewHolder(cardView);
}
使用者選取 ImageCardView
時,即可展開
以您指定的背景顏色顯示文字區域,如圖 1 所示。
這個頁面中的內容和程式碼範例均受《內容授權》中的授權所規範。Java 與 OpenJDK 是 Oracle 和/或其關係企業的商標或註冊商標。
上次更新時間:2025-07-27 (世界標準時間)。
[null,null,["上次更新時間:2025-07-27 (世界標準時間)。"],[],[],null,["# Provide a card view\n\nBuild better with Compose \nCreate beautiful UIs with minimal code using Jetpack Compose for Android TV OS. \n[Compose for TV →](/training/tv/playback/compose) \n\nIn the previous lesson, you created a catalog browser, implemented in a browse fragment, that\ndisplays a list of media items. In this lesson, you create the card views for your media items and\npresent them in the browse fragment.\n\nThe [BaseCardView](/reference/androidx/leanback/widget/BaseCardView)\nclass and subclasses display the metadata associated with a media item. The\n[ImageCardView](/reference/androidx/leanback/widget/ImageCardView)\nclass used in this lesson displays an image for the content along with the media item's title.\n\nSee also the sample implementation in the\n[Leanback sample app](https://github.com/android/tv-samples/tree/main/Leanback)\n.\n\n**Figure 1.** The Leanback sample app image card view when selected.\n\nCreate a card presenter\n-----------------------\n\nA [Presenter](/reference/androidx/leanback/widget/Presenter) generates views and binds objects to them\non demand. In the browse fragment where your app presents its content to the user, you create a\n`Presenter` for the content cards and pass it to the adapter\nthat adds the content to the screen. In the following code, the `CardPresenter` is created\nin the [onLoadFinished()](/reference/androidx/loader/app/LoaderManager.LoaderCallbacks#onLoadFinished(androidx.loader.content.Loader%3CD%3E,D))\ncallback of the [LoaderManager](/reference/androidx/loader/app/LoaderManager): \n\n### Kotlin\n\n```kotlin\noverride fun onLoadFinished(loader: Loader\u003cHashMap\u003cString, List\u003cMovie\u003e\u003e\u003e, data: HashMap\u003cString, List\u003cMovie\u003e\u003e) {\n rowsAdapter = ArrayObjectAdapter(ListRowPresenter())\n val cardPresenter = CardPresenter()\n\n var i = 0L\n\n data.entries.forEach { entry -\u003e\n val listRowAdapter = ArrayObjectAdapter(cardPresenter).apply {\n entry.value.forEach { movie -\u003e\n add(movie)\n }\n }\n\n val header = HeaderItem(i, entry.key)\n i++\n rowsAdapter.add(ListRow(header, listRowAdapter))\n }\n\n val gridHeader = HeaderItem(i, getString(R.string.more_samples))\n\n val gridRowAdapter = ArrayObjectAdapter(GridItemPresenter()).apply {\n add(getString(R.string.grid_view))\n add(getString(R.string.error_fragment))\n add(getString(R.string.personal_settings))\n }\n rowsAdapter.add(ListRow(gridHeader, gridRowAdapter))\n\n adapter = rowsAdapter\n\n updateRecommendations()\n}\n```\n\n### Java\n\n```java\n@Override\npublic void onLoadFinished(Loader\u003cHashMap\u003cString, List\u003cMovie\u003e\u003e\u003e arg0,\n HashMap\u003cString, List\u003cMovie\u003e\u003e data) {\n\n rowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());\n CardPresenter cardPresenter = new CardPresenter();\n\n int i = 0;\n\n for (Map.Entry\u003cString, List\u003cMovie\u003e\u003e entry : data.entrySet()) {\n ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(cardPresenter);\n List\u003cMovie\u003e list = entry.getValue();\n\n for (int j = 0; j \u003c list.size(); j++) {\n listRowAdapter.add(list.get(j));\n }\n HeaderItem header = new HeaderItem(i, entry.getKey());\n i++;\n rowsAdapter.add(new ListRow(header, listRowAdapter));\n }\n\n HeaderItem gridHeader = new HeaderItem(i, getString(R.string.more_samples));\n\n GridItemPresenter gridPresenter = new GridItemPresenter();\n ArrayObjectAdapter gridRowAdapter = new ArrayObjectAdapter(gridPresenter);\n gridRowAdapter.add(getString(R.string.grid_view));\n gridRowAdapter.add(getString(R.string.error_fragment));\n gridRowAdapter.add(getString(R.string.personal_settings));\n rowsAdapter.add(new ListRow(gridHeader, gridRowAdapter));\n\n setAdapter(rowsAdapter);\n\n updateRecommendations();\n}\n```\n\nCreate a card view\n------------------\n\nIn this step, you build the card presenter with a view holder for the card view that describes\nyour media content items. Note that each presenter must create only one view type. If you have two\ncard view types, then you need two card presenters.\n\nIn the [Presenter](/reference/androidx/leanback/widget/Presenter), implement an\n[onCreateViewHolder()](/reference/androidx/leanback/widget/Presenter#onCreateViewHolder(android.view.ViewGroup))\ncallback that creates a view holder that can be used to display a content item: \n\n### Kotlin\n\n```kotlin\nprivate const val CARD_WIDTH = 313\nprivate const val CARD_HEIGHT = 176\n\nclass CardPresenter : Presenter() {\n\n private lateinit var mContext: Context\n private lateinit var defaultCardImage: Drawable\n\n override fun onCreateViewHolder(parent: ViewGroup): Presenter.ViewHolder {\n mContext = parent.context\n defaultCardImage = mContext.resources.getDrawable(R.drawable.movie)\n ...\n```\n\n### Java\n\n```java\n@Override\npublic class CardPresenter extends Presenter {\n\n private Context context;\n private static int CARD_WIDTH = 313;\n private static int CARD_HEIGHT = 176;\n private Drawable defaultCardImage;\n\n @Override\n public ViewHolder onCreateViewHolder(ViewGroup parent) {\n context = parent.getContext();\n defaultCardImage = context.getResources().getDrawable(R.drawable.movie);\n...\n```\n\nIn the [onCreateViewHolder()](/reference/androidx/leanback/widget/Presenter#onCreateViewHolder(android.view.ViewGroup)) method,\ncreate a card view for content items. The following sample uses an\n[ImageCardView](/reference/androidx/leanback/widget/ImageCardView).\n\nWhen a card is selected, the default behavior expands it to a larger size. If you want to designate\na different color for the selected card, call [setSelected()](/reference/androidx/leanback/widget/BaseCardView#setSelected(boolean))\nas shown here: \n\n### Kotlin\n\n```kotlin\n ...\n val cardView = object : ImageCardView(context) {\n override fun setSelected(selected: Boolean) {\n val selected_background = context.resources.getColor(R.color.detail_background)\n val default_background = context.resources.getColor(R.color.default_background)\n val color = if (selected) selected_background else default_background\n findViewById\u003cView\u003e(R.id.info_field).setBackgroundColor(color)\n super.setSelected(selected)\n }\n }\n ...\n```\n\n### Java\n\n```java\n...\n ImageCardView cardView = new ImageCardView(context) {\n @Override\n public void setSelected(boolean selected) {\n int selected_background = context.getResources().getColor(R.color.detail_background);\n int default_background = context.getResources().getColor(R.color.default_background);\n int color = selected ? selected_background : default_background;\n findViewById(R.id.info_field).setBackgroundColor(color);\n super.setSelected(selected);\n }\n };\n...\n```\n\nWhen the user opens your app, the [Presenter.ViewHolder](/reference/androidx/leanback/widget/Presenter.ViewHolder)\ndisplays the `CardView` objects for your content items. You need to set these to receive\nfocus from the D-pad controller by calling [setFocusable(true)](/reference/android/view/View#setFocusable(boolean))\nand [setFocusableInTouchMode(true)](/reference/android/view/View#setFocusableInTouchMode(boolean)),\nas shown in the following code: \n\n### Kotlin\n\n```kotlin\n ...\n cardView.isFocusable = true\n cardView.isFocusableInTouchMode = true\n return ViewHolder(cardView)\n}\n```\n\n### Java\n\n```java\n...\n cardView.setFocusable(true);\n cardView.setFocusableInTouchMode(true);\n return new ViewHolder(cardView);\n}\n```\n\nWhen the user selects the [ImageCardView](/reference/androidx/leanback/widget/ImageCardView), it expands\nto reveal its text area with the background color you specify, as shown in figure 1."]]