Android Studio V3.12環(huán)境下TV開發(fā)教程(五)建立電視回放應(yīng)用

Android Studio V3.12環(huán)境下TV開發(fā)教程

(轉(zhuǎn)自Android官網(wǎng)https://developer.android.com/training/tv/start)

文章源自:光谷佳武 https://blog.csdn.net/jiawuhan/article/details/80619382

建立電視回放應(yīng)用

瀏覽和播放媒體文件通常是電視應(yīng)用程序提供的用戶體驗的一部分。?從零開始構(gòu)建這樣的體驗,同時確保其快速,流暢和有吸引力可能是相當(dāng)具有挑戰(zhàn)性的。?無論您的應(yīng)用是否提供對小型或大型媒體目錄的訪問,允許用戶快速瀏覽選項并獲取他們想要的內(nèi)容非常重要。

Android框架提供了用于使用v17 leanback支持庫為這些類型的應(yīng)用程序構(gòu)建用戶界面的類。?這個庫提供了一個類框架,用于創(chuàng)建一個高效且熟悉的界面,以最少的代碼瀏覽和播放媒體文件。?這些課程旨在進行擴展和定制,以便您可以創(chuàng)建獨特的應(yīng)用體驗。

本課程向您展示如何使用Leanback電視支持庫構(gòu)建瀏覽和播放媒體內(nèi)容的電視應(yīng)用程序。

主題

創(chuàng)建一個目錄瀏覽器

了解如何使用Leanback支持庫為媒體目錄構(gòu)建瀏覽界面。

提供卡片視圖

了解如何使用Leanback支持庫為內(nèi)容項目構(gòu)建卡片視圖。

建立詳細信息視圖

了解如何使用Leanback支持庫為媒體項目構(gòu)建詳細信息頁面。

使用Leanback的運輸控制

了解如何使用Leanback支持庫為您的視頻播放器構(gòu)建傳輸控件。

顯示一張現(xiàn)在玩的牌

了解如何使用MediaSession在主屏幕上顯示正在使用的即時貼。

直接在表面上渲染視頻

了解您的應(yīng)用如何直接在主屏幕的表面上呈現(xiàn)預(yù)覽視頻。

添加引導(dǎo)步驟

了解如何使用Leanback支持庫來指導(dǎo)用戶完成一系列決策。

首次將用戶引入您的應(yīng)用

了解如何使用Leanback支持庫向初次使用者展示如何充分利用您的應(yīng)用程序。

啟用后臺播放

了解如何在用戶點擊主頁時繼續(xù)播放。

創(chuàng)建一個目錄瀏覽器

運行在電視上的媒體應(yīng)用程序需要允許用戶瀏覽其內(nèi)容產(chǎn)品,進行選擇并開始播放內(nèi)容。?這種類型的應(yīng)用程序的內(nèi)容瀏覽體驗應(yīng)該簡單直觀,并且在視覺上令人愉悅且引人入勝。

本課討論如何使用v17 leanback支持庫提供的類來實現(xiàn)用于從應(yīng)用媒體目錄中瀏覽音樂或視頻的用戶界面。

圖1.?Leanback示例應(yīng)用程序瀏覽片段顯示視頻目錄數(shù)據(jù)。

創(chuàng)建媒體瀏覽布局

leanback庫中的BrowseFragment類允許您使用最少的代碼創(chuàng)建用于瀏覽媒體項目類別和行的主要布局。?以下示例顯示如何創(chuàng)建包含BrowseFragment對象的布局:

? ?

應(yīng)用程序的主要活動設(shè)置此視圖,如以下示例所示:

public class MainActivity extends Activity {? ? @Override? ? public void onCreate(Bundle savedInstanceState) {? ? ? ? super.onCreate(savedInstanceState);? ? ? ? setContentView(R.layout.main);? ? }...

BrowseFragment方法使用視頻數(shù)據(jù)和UI元素填充視圖,并設(shè)置布局參數(shù)(如圖標(biāo),標(biāo)題以及是否啟用類別標(biāo)題)。

有關(guān)設(shè)置UI元素的更多信息,請參閱設(shè)置?UI元素。

有關(guān)隱藏標(biāo)題的更多信息,請參閱隱藏或禁用標(biāo)題。

實現(xiàn)BrowseFragment方法的應(yīng)用程序的子類還為UI元素上的用戶操作設(shè)置事件偵聽器,并準備后臺管理器,如以下示例所示:

public class MainFragment extends BrowseFragment implements? ? ? ? LoaderManager.LoaderCallbacks>> {...? ? @Override? ? public void onActivityCreated(Bundle savedInstanceState) {? ? ? ? super.onActivityCreated(savedInstanceState);? ? ? ? loadVideoData();? ? ? ? prepareBackgroundManager();? ? ? ? setupUIElements();? ? ? ? setupEventListeners();? ? }...? ? private void prepareBackgroundManager() {? ? ? ? mBackgroundManager = BackgroundManager.getInstance(getActivity());? ? ? ? mBackgroundManager.attach(getActivity().getWindow());? ? ? ? mDefaultBackground = getResources()? ? ? ? ? ? .getDrawable(R.drawable.default_background);? ? ? ? mMetrics = new DisplayMetrics();? ? ? ? getActivity().getWindowManager().getDefaultDisplay().getMetrics(mMetrics);? ? }? ? private void setupUIElements() {? ? ? ? setBadgeDrawable(getActivity().getResources()? ? ? ? ? ? .getDrawable(R.drawable.videos_by_google_banner));? ? ? ? // Badge, when set, takes precedent over title? ? ? ? setTitle(getString(R.string.browse_title));? ? ? ? setHeadersState(HEADERS_ENABLED);? ? ? ? setHeadersTransitionOnBackEnabled(true);? ? ? ? // set headers background color? ? ? ? setBrandColor(getResources().getColor(R.color.fastlane_background));? ? ? ? // set search icon color? ? ? ? setSearchAffordanceColor(getResources().getColor(R.color.search_opaque));? ? }? ? private void loadVideoData() {? ? ? ? VideoProvider.setContext(getActivity());? ? ? ? mVideosUrl = getActivity().getResources().getString(R.string.catalog_url);? ? ? ? getLoaderManager().initLoader(0, null, this);? ? }? ? private void setupEventListeners() {? ? ? ? setOnSearchClickedListener(new View.OnClickListener() {? ? ? ? ? ? @Override? ? ? ? ? ? public void onClick(View view) {? ? ? ? ? ? ? ? Intent intent = new Intent(getActivity(), SearchActivity.class);? ? ? ? ? ? ? ? startActivity(intent);? ? ? ? ? ? }? ? ? ? });? ? ? ? setOnItemViewClickedListener(new ItemViewClickedListener());? ? ? ? setOnItemViewSelectedListener(new ItemViewSelectedListener());? ? }...

設(shè)置UI元素

在上面的示例中,私有方法setupUIElements()調(diào)用了幾個BrowseFragment方法來設(shè)置媒體目錄瀏覽器的樣式:

setBadgeDrawable()將指定的可繪制資源放置在瀏覽片段的右上角,如圖1和2所示。如果還調(diào)用了setTitle()?,則此方法將用可繪制資源替換標(biāo)題字符串。?可繪制的資源應(yīng)該是52dps高。

除非setBadgeDrawable()?,否則setBadgeDrawable()會在瀏覽片段的右上角設(shè)置標(biāo)題字符串。

setHeadersState()setHeadersTransitionOnBackEnabled()隱藏或禁用標(biāo)題。?有關(guān)更多信息,請參閱隱藏或禁用標(biāo)題?。

setBrandColor()使用指定的顏色值為瀏覽片段中的UI元素(特別是標(biāo)題部分背景顏色setBrandColor()設(shè)置背景顏色。

setSearchAffordanceColor()用指定的顏色值設(shè)置搜索圖標(biāo)的顏色。?搜索圖標(biāo)出現(xiàn)在瀏覽片段的左上角,如圖1和2所示。

自定義標(biāo)題視圖

圖1中顯示的瀏覽片段列出了左側(cè)窗格中的視頻類別名稱(行標(biāo)題)。?文本視圖顯示視頻數(shù)據(jù)庫中的這些類別名稱。?您可以自定義標(biāo)題以在更復(fù)雜的布局中包含其他視圖。?以下部分顯示如何包含圖像視圖,該圖像視圖在類別名稱旁邊顯示圖標(biāo),如圖2所示。

圖2.瀏覽片段中的行標(biāo)題,帶有圖標(biāo)和文本標(biāo)簽。

行標(biāo)題的布局定義如下:

? ? ? ?

使用Presenter并實現(xiàn)抽象方法來創(chuàng)建,綁定和取消綁定視圖持有者。?以下示例顯示如何使用兩個視圖(一個ImageView和一個TextView來綁定視圖。

public class IconHeaderItemPresenter extends Presenter {? ? @Override? ? public ViewHolder onCreateViewHolder(ViewGroup viewGroup) {? ? ? ? LayoutInflater inflater = (LayoutInflater) viewGroup.getContext()? ? ? ? ? ? ? ? .getSystemService(Context.LAYOUT_INFLATER_SERVICE);? ? ? ? View view = inflater.inflate(R.layout.icon_header_item, null);? ? ? ? return new ViewHolder(view);? ? }? ? @Override? ? public void onBindViewHolder(ViewHolder viewHolder, Object o) {? ? ? ? HeaderItem headerItem = ((ListRow) o).getHeaderItem();? ? ? ? View rootView = viewHolder.view;? ? ? ? ImageView iconView = (ImageView) rootView.findViewById(R.id.header_icon);? ? ? ? Drawable icon = rootView.getResources().getDrawable(R.drawable.ic_action_video, null);? ? ? ? iconView.setImageDrawable(icon);? ? ? ? TextView label = (TextView) rootView.findViewById(R.id.header_label);? ? ? ? label.setText(headerItem.getName());? ? }? ? @Override? ? public void onUnbindViewHolder(ViewHolder viewHolder) {? ? // no op? ? }}

你的頭文件必須是可以調(diào)焦的,這樣D-pad可以用來滾動它們。?有兩種選擇:

將你的視圖設(shè)置為onBindViewHolder()焦點:

@Overridepublic void onBindViewHolder(ViewHolder viewHolder, Object o) {? ? HeaderItem headerItem = ((ListRow) o).getHeaderItem();? ? View rootView = viewHolder.view;? ? rootView.setFocusable(true) // Allows the D-Pad to navigate to this header item? ? //...}

將您的布??局設(shè)置為可對焦:


? ?android:focusable="true">

最后,在顯示目錄瀏覽器的BrowseFragment實現(xiàn)中,使用setHeaderPresenterSelector()方法為行標(biāo)題設(shè)置演示者,如以下示例所示。

setHeaderPresenterSelector(new PresenterSelector() {? ? @Override? ? public Presenter getPresenter(Object o) {? ? ? ? return new IconHeaderItemPresenter();? ? }});

有關(guān)完整示例,請參閱leanback示例中的IconHeaderItemPresenter。

隱藏或禁用標(biāo)題

例如,有時您可能不希望行標(biāo)題出現(xiàn):當(dāng)沒有足夠的類別需要可滾動列表時。?在片段的onActivityCreated()方法中調(diào)用BrowseFragment.setHeadersState()方法來隱藏或禁用行標(biāo)題。?setHeadersState()方法將以下常量之一作為參數(shù),設(shè)置瀏覽片段中標(biāo)題的初始狀態(tài):

HEADERS_ENABLED?- 創(chuàng)建瀏覽片段活動時,默認情況下會啟用并顯示標(biāo)題。?標(biāo)題的顯示如圖1和2所示。

HEADERS_HIDDEN?- 創(chuàng)建瀏覽片段活動時,標(biāo)題默認情況下處于啟用和隱藏狀態(tài)。?屏幕的標(biāo)題部分已折疊,如提供卡片視圖的?圖1所示。?用戶可以選擇折疊頁眉部分來展開它。

HEADERS_DISABLED?- 創(chuàng)建瀏覽片段活動時,標(biāo)題默認處于禁用狀態(tài),并且不會顯示。

如果設(shè)置了HEADERS_ENABLEDHEADERS_HIDDEN則可以調(diào)用setHeadersTransitionOnBackEnabled()以支持從行中所選內(nèi)容項移回行標(biāo)題。?這是默認啟用的(如果你不調(diào)用方法),但是如果你想自己處理后退運動,你應(yīng)該將false值傳遞給setHeadersTransitionOnBackEnabled()并實現(xiàn)你自己的后端堆棧處理。

顯示媒體列表

BrowseFragment類允許您使用適配器和演示BrowseFragment從媒體目錄中定義和顯示可瀏覽的媒體內(nèi)容類別和媒體項目。?適配器使您能夠連接到包含媒體目錄信息的本地或聯(lián)機數(shù)據(jù)源。?適配器使用演示者創(chuàng)建視圖并將數(shù)據(jù)綁定到這些視圖以在屏幕上顯示項目。

以下示例代碼顯示了用于顯示字符串?dāng)?shù)據(jù)的Presenter的實現(xiàn):

public class StringPresenter extends Presenter {? ? private static final String TAG = "StringPresenter";? ? public ViewHolder onCreateViewHolder(ViewGroup parent) {? ? ? ? TextView textView = new TextView(parent.getContext());? ? ? ? textView.setFocusable(true);? ? ? ? textView.setFocusableInTouchMode(true);? ? ? ? textView.setBackground(? ? ? ? ? ? ? ? parent.getContext().getResources().getDrawable(R.drawable.text_bg));? ? ? ? return new ViewHolder(textView);? ? }? ? public void onBindViewHolder(ViewHolder viewHolder, Object item) {? ? ? ? ((TextView) viewHolder.view).setText(item.toString());? ? }? ? public void onUnbindViewHolder(ViewHolder viewHolder) {? ? ? ? // no op? ? }}

一旦為媒體項目構(gòu)建了演示者類,就可以構(gòu)建一個適配器并將其附加到BrowseFragment以在屏幕上顯示這些項目以供用戶瀏覽。?以下示例代碼演示了如何使用前面的代碼示例中顯示的StringPresenter類構(gòu)造適配器以顯示這些類別中的類別和項目:

private ArrayObjectAdapter mRowsAdapter;private static final int NUM_ROWS = 4;@Overrideprotected void onCreate(Bundle savedInstanceState) {? ? ...? ? buildRowsAdapter();}private void buildRowsAdapter() {? ? mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());? ? for (int i = 0; i < NUM_ROWS; ++i) {? ? ? ? ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(? ? ? ? ? ? ? ? new StringPresenter());? ? ? ? listRowAdapter.add("Media Item 1");? ? ? ? listRowAdapter.add("Media Item 2");? ? ? ? listRowAdapter.add("Media Item 3");? ? ? ? HeaderItem header = new HeaderItem(i, "Category " + i);? ? ? ? mRowsAdapter.add(new ListRow(header, listRowAdapter));? ? }? ? mBrowseFragment.setAdapter(mRowsAdapter);}

此示例顯示適配器的靜態(tài)實現(xiàn)。?典型的媒體瀏覽應(yīng)用程序使用來自在線數(shù)據(jù)庫或Web服務(wù)的數(shù)據(jù)。?有關(guān)使用從Web檢索的數(shù)據(jù)的瀏覽應(yīng)用程序的示例,請參閱Android Leanback示例應(yīng)用程序?。

更新背景

為了在電視上為媒體瀏覽應(yīng)用增加視覺趣味,您可以在用戶瀏覽內(nèi)容時更新背景圖片。?這項技術(shù)可以使您的應(yīng)用更具電影感和愉悅感。

Leanback支持庫提供了一個BackgroundManager類,用于更改電視應(yīng)用程序活動的背景。?以下示例顯示如何創(chuàng)建一個簡單方法來更新電視應(yīng)用程序活動中的背景:

protected void updateBackground(Drawable drawable) {? ? BackgroundManager.getInstance(this).setDrawable(drawable);}

當(dāng)用戶瀏覽媒體列表時,許多現(xiàn)有的媒體瀏覽應(yīng)用會自動更新背景。?為了做到這一點,您可以設(shè)置一個選擇偵聽器,根據(jù)用戶的當(dāng)前選擇自動更新背景。?以下示例顯示如何設(shè)置OnItemViewSelectedListener類來捕獲選擇事件并更新背景:

protected void clearBackground() {? ? BackgroundManager.getInstance(this).setDrawable(mDefaultBackground);}protected OnItemViewSelectedListener getDefaultItemViewSelectedListener() {? ? return new OnItemViewSelectedListener() {? ? ? ? @Override? ? ? ? public void onItemSelected(Object item, Row row) {? ? ? ? ? ? if (item instanceof Movie ) {? ? ? ? ? ? ? ? Drawable background = ((Movie)item).getBackdropDrawable();? ? ? ? ? ? ? ? updateBackground(background);? ? ? ? ? ? } else {? ? ? ? ? ? ? ? clearBackground();? ? ? ? ? ? }? ? ? ? }? ? };}

注意:上面的實現(xiàn)是一個簡單的例子,用于說明。?在自己的應(yīng)用程序中創(chuàng)建此功能時,應(yīng)考慮在單獨的線程中運行后臺更新操作以獲得更好的性能。?此外,如果您計劃更新背景以響應(yīng)用戶滾動瀏覽項目,請考慮增加一段時間來延遲背景圖片更新,直到用戶安置一個項目。?這種技術(shù)避免了過多的背景圖像更新。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,618評論 19 139
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,955評論 1 92
  • 教別人怎樣閱讀的書很多,《深閱讀》是其中比較特別的一本。 這本書的作者,齋藤孝,畢業(yè)于東京大學(xué)法學(xué)部,并在該大學(xué)研...
    伍鋅閱讀 835評論 2 5
  • 經(jīng)典心理測驗到底適不適合用于企業(yè)用人的考察和篩選? 本文為作者的文章原稿,修改版已授權(quán)發(fā)表于微信公眾號@智鼎人才官...
    EssieL閱讀 1,526評論 0 2
  • 時光塌下,吹散了的一抹浮華終是隨著落花悠悠落于相思樹下,曾言過,你無畏金戈鐵馬,一把素琴,即已走遍天下。風(fēng)終...
    尹夕顏閱讀 132評論 0 1

友情鏈接更多精彩內(nèi)容