Android Studio TV开发教程(五)建立电视回放应用
Android Studio TV开发教程
(转自Android官网https://developer.android.com/training/tv/start)
文章源自:光谷佳武 https://blog.csdn.net/jiawuhan/article/details/80619382
建立电视回放应用
浏览和播放媒体文件通常是电视应用程序提供的用户体验的一部分。 从零开始构建这样的体验,同时确保其快速,流畅和有吸引力可能是相当具有挑战性的。 无论您的应用是否提供对小型或大型媒体目录的访问,允许用户快速浏览选项并获取他们想要的内容非常重要。
Android框架提供了用于使用v17 leanback支持库为这些类型的应用程序构建用户界面的类。 这个库提供了一个类框架,用于创建一个高效且熟悉的界面,以最少的代码浏览和播放媒体文件。 这些课程旨在进行扩展和定制,以便您可以创建独特的应用体验。
本课程向您展示如何使用Leanback电视支持库构建浏览和播放媒体内容的电视应用程序。
主题
- 创建一个目录浏览器
- 了解如何使用Leanback支持库为媒体目录构建浏览界面。
- 提供卡片视图
- 了解如何使用Leanback支持库为内容项目构建卡片视图。
- 建立详细信息视图
- 了解如何使用Leanback支持库为媒体项目构建详细信息页面。
- 使用Leanback的运输控制
- 了解如何使用Leanback支持库为您的视频播放器构建传输控件。
- 显示一张现在玩的牌
- 了解如何使用MediaSession在主屏幕上显示正在使用的即时贴。
- 直接在表面上渲染视频
- 了解您的应用如何直接在主屏幕的表面上呈现预览视频。
- 添加引导步骤
- 了解如何使用Leanback支持库来指导用户完成一系列决策。
- 首次将用户引入您的应用
- 了解如何使用Leanback支持库向初次使用者展示如何充分利用您的应用程序。
- 启用后台播放
- 了解如何在用户点击主页时继续播放。
创建一个目录浏览器
运行在电视上的媒体应用程序需要允许用户浏览其内容产品,进行选择并开始播放内容。 这种类型的应用程序的内容浏览体验应该简单直观,并且在视觉上令人愉悦且引人入胜。
本课讨论如何使用v17 leanback支持库提供的类来实现用于从应用媒体目录中浏览音乐或视频的用户界面。
图1. Leanback示例应用程序浏览片段显示视频目录数据。
创建媒体浏览布局
leanback库中的BrowseFragment
类允许您使用最少的代码创建用于浏览媒体项目类别和行的主要布局。 以下示例显示如何创建包含BrowseFragment
对象的布局:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/main_frame"android:layout_width="match_parent"android:layout_height="match_parent"><fragmentandroid:name="com.example.android.tvleanback.ui.MainFragment"android:id="@+id/main_browse_fragment"android:layout_width="match_parent"android:layout_height="match_parent" /></FrameLayout>
应用程序的主要活动设置此视图,如以下示例所示:
public class MainActivity extends Activity {@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);} ...
BrowseFragment
方法使用视频数据和UI元素填充视图,并设置布局参数(如图标,标题以及是否启用类别标题)。
- 有关设置UI元素的更多信息,请参阅设置 UI元素。
- 有关隐藏标题的更多信息,请参阅隐藏或禁用标题。
实现BrowseFragment
方法的应用程序的子类还为UI元素上的用户操作设置事件侦听器,并准备后台管理器,如以下示例所示:
public class MainFragment extends BrowseFragment implementsLoaderManager.LoaderCallbacks<HashMap<String, List<Movie>>> {...@Overridepublic 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 titlesetTitle(getString(R.string.browse_title));setHeadersState(HEADERS_ENABLED);setHeadersTransitionOnBackEnabled(true);// set headers background colorsetBrandColor(getResources().getColor(R.color.fastlane_background));// set search icon colorsetSearchAffordanceColor(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() {@Overridepublic void onClick(View view) {Intent intent = new Intent(getActivity(), SearchActivity.class);startActivity(intent);}});setOnItemViewClickedListener(new ItemViewClickedListener());setOnItemViewSelectedListener(new ItemViewSelectedListener());} ...
设置UI元素
在上面的示例中,私有方法setupUIElements()
调用了几个BrowseFragment
方法来设置媒体目录浏览器的样式:
setBadgeDrawable()
将指定的可绘制资源放置在浏览片段的右上角,如图1和2所示。如果还调用了setTitle()
,则此方法将用可绘制资源替换标题字符串。 可绘制的资源应该是52dps高。- 除非
setBadgeDrawable()
,否则setBadgeDrawable()
会在浏览片段的右上角设置标题字符串。 setHeadersState()
和setHeadersTransitionOnBackEnabled()
隐藏或禁用标题。 有关更多信息,请参阅隐藏或禁用标题 。setBrandColor()
使用指定的颜色值为浏览片段中的UI元素(特别是标题部分背景颜色setBrandColor()
设置背景颜色。setSearchAffordanceColor()
用指定的颜色值设置搜索图标的颜色。 搜索图标出现在浏览片段的左上角,如图1和2所示。
自定义标题视图
图1中显示的浏览片段列出了左侧窗格中的视频类别名称(行标题)。 文本视图显示视频数据库中的这些类别名称。 您可以自定义标题以在更复杂的布局中包含其他视图。 以下部分显示如何包含图像视图,该图像视图在类别名称旁边显示图标,如图2所示。
图2.浏览片段中的行标题,带有图标和文本标签。
行标题的布局定义如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"><ImageViewandroid:id="@+id/header_icon"android:layout_width="32dp"android:layout_height="32dp" /><TextViewandroid:id="@+id/header_label"android:layout_marginTop="6dp"android:layout_width="wrap_content"android:layout_height="wrap_content" /></LinearLayout>
使用Presenter
并实现抽象方法来创建,绑定和取消绑定视图持有者。 以下示例显示如何使用两个视图(一个ImageView
和一个TextView
来绑定视图。
public class IconHeaderItemPresenter extends Presenter {@Overridepublic 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);}@Overridepublic 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());}@Overridepublic void onUnbindViewHolder(ViewHolder viewHolder) {// no op} }
你的头文件必须是可以调焦的,这样D-pad可以用来滚动它们。 有两种选择:
- 将你的视图设置为
onBindViewHolder()
焦点:@Override public 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//... }
- 将您的布局设置为可对焦:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"...android:focusable="true">
最后,在显示目录浏览器的BrowseFragment
实现中,使用setHeaderPresenterSelector()
方法为行标题设置演示者,如以下示例所示。
setHeaderPresenterSelector(new PresenterSelector() {@Overridepublic Presenter getPresenter(Object o) {return new IconHeaderItemPresenter();} });
有关完整示例,请参阅leanback示例中的IconHeaderItemPresenter。
隐藏或禁用标题
例如,有时您可能不希望行标题出现:当没有足够的类别需要可滚动列表时。 在片段的onActivityCreated()
方法中调用BrowseFragment.setHeadersState()
方法来隐藏或禁用行标题。 setHeadersState()
方法将以下常量之一作为参数,设置浏览片段中标题的初始状态:
HEADERS_ENABLED
- 创建浏览片段活动时,默认情况下会启用并显示标题。 标题的显示如图1和2所示。HEADERS_HIDDEN
- 创建浏览片段活动时,标题默认情况下处于启用和隐藏状态。 屏幕的标题部分已折叠,如提供卡片视图的 图1所示。 用户可以选择折叠页眉部分来展开它。HEADERS_DISABLED
- 创建浏览片段活动时,标题默认处于禁用状态,并且不会显示。
如果设置了HEADERS_ENABLED
或HEADERS_HIDDEN
则可以调用setHeadersTransitionOnBackEnabled()
以支持从行中所选内容项移回行标题。 这是默认启用的(如果你不调用方法),但是如果你想自己处理后退运动,你应该将false
值传递给setHeadersTransitionOnBackEnabled()
并实现你自己的后端堆栈处理。
显示媒体列表
BrowseFragment
类允许您使用适配器和演示BrowseFragment
从媒体目录中定义和显示可浏览的媒体内容类别和媒体项目。 适配器使您能够连接到包含媒体目录信息的本地或联机数据源。 适配器使用演示者创建视图并将数据绑定到这些视图以在屏幕上显示项目。
以下示例代码显示了用于显示字符串数据的Presenter
的实现:
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} }
一旦为媒体项目构建了演示者类,就可以构建一个适配器并将其附加到BrowseFragment
以在屏幕上显示这些项目以供用户浏览。 以下示例代码演示了如何使用前面的代码示例中显示的StringPresenter
类构造适配器以显示这些类别中的类别和项目:
private ArrayObjectAdapter mRowsAdapter; private static final int NUM_ROWS = 4;@Override protected 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); }
此示例显示适配器的静态实现。 典型的媒体浏览应用程序使用来自在线数据库或Web服务的数据。 有关使用从Web检索的数据的浏览应用程序的示例,请参阅Android Leanback示例应用程序 。
更新背景
为了在电视上为媒体浏览应用增加视觉趣味,您可以在用户浏览内容时更新背景图片。 这项技术可以使您的应用更具电影感和愉悦感。
Leanback支持库提供了一个BackgroundManager
类,用于更改电视应用程序活动的背景。 以下示例显示如何创建一个简单方法来更新电视应用程序活动中的背景:
protected void updateBackground(Drawable drawable) {BackgroundManager.getInstance(this).setDrawable(drawable); }
当用户浏览媒体列表时,许多现有的媒体浏览应用会自动更新背景。 为了做到这一点,您可以设置一个选择侦听器,根据用户的当前选择自动更新背景。 以下示例显示如何设置OnItemViewSelectedListener
类来捕获选择事件并更新背景:
protected void clearBackground() {BackgroundManager.getInstance(this).setDrawable(mDefaultBackground); }protected OnItemViewSelectedListener getDefaultItemViewSelectedListener() {return new OnItemViewSelectedListener() {@Overridepublic void onItemSelected(Object item, Row row) {if (item instanceof Movie ) {Drawable background = ((Movie)item).getBackdropDrawable();updateBackground(background);} else {clearBackground();}}}; }
注意:上面的实现是一个简单的例子,用于说明。 在自己的应用程序中创建此功能时,应考虑在单独的线程中运行后台更新操作以获得更好的性能。 此外,如果您计划更新背景以响应用户滚动浏览项目,请考虑增加一段时间来延迟背景图片更新,直到用户安置一个项目。 这种技术避免了过多的背景图像更新。
Android Studio TV开发教程(五)建立电视回放应用相关推荐
- Android Studio TV开发教程(十五) Android N及更早版本中的建议
Android Studio TV开发教程 (转自Android官网https://developer.android.com/training/tv/start) 文章源自:光谷佳武 https:/ ...
- Android Studio TV开发教程(十六)让电视应用程序可搜索
Android Studio TV开发教程 (转自Android官网https://developer.android.com/training/tv/start) 文章源自:光谷佳武 https:/ ...
- Android Studio TV开发教程(十二)帮助用户在电视上找到您的内容
Android Studio TV开发教程 (转自Android官网https://developer.android.com/training/tv/start) 文章源自:光谷佳武 https:/ ...
- Android Studio TV开发教程(二)管理电视控制器
Android Studio TV开发教程 (转自Android官网https://developer.android.com/training/tv/start) 文章源自:光谷佳武 https:/ ...
- Android Studio TV开发教程(一)处理电视硬件
Android Studio TV开发教程 (转自Android官网https://developer.android.com/training/tv/start) 文章源自:光谷佳武 https:/ ...
- android数据库开发案例教程,Android Studio项目开发教程 第6章 数据库编程(30页)-原创力文档...
;目录;;;;;;6.3 SQLite数据库的操作;;;;表 6.1 Cursor类提供的常用方法;;;;;6.5购物商城的数据库编程;使用Activity类中的 getPreferences方法获取 ...
- Android电视切换回放,Android Studio V3.12环境下TV开发教程(五)建立电视回放应用...
Android Studio V3.12环境下TV开发教程 文章源自:光谷佳武 https://blog.csdn.net/jiawuhan/article/details/80619382 浏览和播 ...
- android studio3.12,Android Studio V3.12环境下TV开发教程(六)提供卡片视图
Android Studio V3.12环境下TV开发教程 文章源自:光谷佳武 https://blog.csdn.net/jiawuhan/article/details/80619656 在上一课 ...
- 第七章 : Git 介绍 (上)[Learn Android Studio 汉化教程]
Learn Android Studio 汉化教程 [翻译]Git介绍 Git版本控制系统(VCS)快速成为Android应用程序开发以及常规的软件编程领域内的事实标准.有别于需要中心服务器支持的早期 ...
最新文章
- python编程300集免费-python 300本电子书合集
- ipvsadm使用和命令
- eureka之EurekaInstanceConfig接口的作用
- Mysql的几个字符串函数【concat、concat_ws、group_concat】
- Google 的开源方法论
- Nicetools:定一个小目标,先做它个1000个工具
- (18)FPGA面试题查找表的原理与结构
- 转:Mac文件权限操作详细记录
- 输入用户名和密码登入到服务器,却显示指定的网络密码不正确,输入了好几次都是这样,这是怎么回事? 用户名和密码没问题 ,一直用的好好地今天就不行了...
- android 时间函数 性能,Android 性能优化——启动时间优化
- jave double相加结果误差+尾巴
- 红外传感器型号和参数_各类红外传感器比较
- 《Linux内核设计与实现》第四章学习笔记——进程调度
- leetcode 排列组合系列
- 如何优化淘宝直通车推广创意标题
- 曲面积分的投影法_在家学|第一类曲面积分与第二类曲面积分的计算
- 编译原理:LL(1)文法 语法分析器(预测分析表法)
- 利用WordPress源代码轻松搭建个人博客站点
- 【934. 最短的桥】
- 从零开始的Wordpress个人网站搭建(图文)
热门文章
- 九型人格和大五类人格对比
- 项目环境搭建【BT Linux面板 7.8.0 】
- 程序员如何发展第二职业?这几种副业方式超赚钱
- 云擎未来,智信天下 | 2023移动云大会来了!
- 开发物体识别桌、_【专利解密】华为如何实现物体检测在大规模场景中的应用;苹果卷入其中?三星显示被要求赔偿前副总裁专利侵权费...
- 【ReID】Joint Discriminative and Generative Learning for Person Re-identification
- 开机自动启动ros节点--robot_upstart
- 泪水:释放感情 滋润生命
- 多个百世快递的物流情况是怎么批量查询的
- 【Chaos Mesh官方文档】Chaosd Introduction