Android Studio V3.12环境下TV开发教程
(转自Android官网https://developer.android.com/training/tv/start)
文章源自:光谷佳武 https://blog.csdn.net/jiawuhan/article/details/80620433
Leanback库具有新的播放控件,可提供改进的用户体验。 对于视频应用程序,传输控件使用向前/向后控件支持视频清理。 清理显示屏时会显示缩略图,以帮助浏览视频。
该库包含抽象类以及为开发人员提供更精细控制的开箱即用实现。 使用预构建的实现,您可以快速构建功能丰富的应用程序,而无需太多编码。 如果您需要更多定制,您可以扩展任何库的预构建组件。
leanback库将用户界面与回放视频的播放器中的传输控件分开。 这是通过两个组件完成的:一个用于显示传输控件(可选视频)的播放片段和一个用于封装媒体播放器的播放器适配器 。
您应用的UI活动应使用PlaybackFragment或VideoFragment 。 两者都包含leanback运输控制:
PlaybackFragment根据需要动画其传输控件以隐藏/显示它们。
VideoFragment扩展了PlaybackFragment并具有SurfaceView来渲染视频。
您可以自定义片段的ObjectAdapter来增强UI。 例如,使用setAdapter()添加“相关视频”行。
PlayerAdapter是一个控制底层媒体播放器的抽象类。 开发人员可以选择预先构建的MediaPlayerAdapter实现,或者编写他们自己的这个类的实现。
您必须使用一些“控制胶水”将播放片段连接到播放器。 leanback库提供两种胶水:
PlaybackBannerControlGlue以“旧样式”绘制播放片段中的传输控件,将它们放置在不透明的背景中。 ( PlaybackBannerControlGlue取代了已弃用的PlaybackControlGlue 。)
PlaybackTransportControlGlue使用具有透明背景的“新样式”控件。
如果您希望您的应用支持视频清理,则必须使用PlaybackTransportControlGlue 。
您还需要指定一个将胶水绑定到回放片段的“胶水主机”,在UI中绘制传输控件并保持它们的状态,并将传输控制事件传递回胶水。 主机必须匹配回放片段类型。 将PlaybackFragmentGlueHost与PlaybackFragmentGlueHost一起使用,并将VideoFragmentGlueHost与VideoFragmentGlueHost一起使用。
下面是一个插图,展示了Leanback运输控制系统的各个部分如何配合在一起:
将您的应用粘合在一起的代码应该位于定义UI的PlaybackFragment或VideoFragment中。
在以下示例中,该应用程序构造PlaybackTransportControlGlue的实例,将其命名为playerGlue ,并将其VideoFragment连接到新创建的MediaPlayerAdapter 。 由于这是一个VideoFragment ,安装程序代码调用setHost()将VideoFragmentGlueHost附加到playerGlue 。 该代码包含在扩展VideoFragment的类中。
public class MyVideoFragment extends VideoFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final PlaybackTransportControlGlue playerGlue = new PlaybackTransportControlGlue(getActivity(), new MediaPlayerAdapter(getActivity())); playerGlue.setHost(new VideoFragmentGlueHost(this)); playerGlue.addPlayerCallback(new PlaybackGlue.PlayerCallback() { @Override public void onPreparedStateChanged(PlaybackGlue glue) { if (glue.isPrepared()) { playerGlue.setSeekProvider(new MySeekProvider()); playerGlue.play(); } } }); playerGlue.setSubtitle("Leanback artist"); playerGlue.setTitle("Leanback team at work"); String uriPath = "android.resource://com.example.android.leanback/raw/video"; playerGlue.getPlayerAdapter().setDataSource(Uri.parse(uriPath)); } }
请注意,设置代码还定义了一个PlayerAdapter.Callback来处理来自媒体播放器的事件。
您可以自定义PlaybackBannerControlGlue和PlaybackTrabsportControlGlue 。 改变PlaybackControlsRow 。
要自定义播放控件顶部的标题和说明,请覆盖onCreateRowPresenter() :
@Override protected PlaybackRowPresenter onCreateRowPresenter() { PlaybackTransportRowPresenter presenter = (PlaybackTransportRowPresenter) super.onCreateRowPresenter(); presenter.setDescriptionPresenter(new MyCustomDescriptionPresenter()); return presenter; }
控件胶水会显示PlaybackControlsRow操作的控件。
PlaybackControlsRow中的操作分配给两组: 主要操作和辅助操作 。 主要组的控件出现在搜索栏上方,而次要组的控件出现在搜索栏下方。 最初,播放/暂停按钮只有一个主要操作,并且没有次要操作。
您可以通过覆盖onCreatePrimaryActions()和onCreateSecondaryActions()来添加主要和次要组的操作。
private PlaybackControlsRow.RepeatAction mRepeatAction; private PlaybackControlsRow.PictureInPictureAction mPipAction; private PlaybackControlsRow.ThumbsUpAction mThumbsUpAction; private PlaybackControlsRow.ThumbsDownAction mThumbsDownAction; private PlaybackControlsRow.SkipPreviousAction mSkipPreviousAction; private PlaybackControlsRow.SkipNextAction mSkipNextAction; private PlaybackControlsRow.FastForwardAction mFastForwardAction; private PlaybackControlsRow.RewindAction mRewindAction; @Override protected void onCreatePrimaryActions(ArrayObjectAdapter primaryActionsAdapter) { // Order matters, super.onCreatePrimaryActions() will create the play / pause action. // Will display as follows: // play/pause, previous, rewind, fast forward, next // > /|| |< << >> >| super.onCreatePrimaryActions(primaryActionsAdapter); primaryActionsAdapter.add(mSkipPreviousAction); primaryActionsAdapter.add(mRewindAction); primaryActionsAdapter.add(mFastForwardAction); primaryActionsAdapter.add(mSkipNextAction); } @Override protected void onCreateSecondaryActions(ArrayObjectAdapter adapter) { super.onCreateSecondaryActions(adapter); adapter.add(mThumbsDownAction); adapter.add(mThumbsUpAction); }
您必须重写onActionClicked()来处理新的操作。
@Override public void onActionClicked(Action action) { if (action == mRewindAction) { // Handle Rewind } else if (action == mFastForwardAction ) { // Handle FastForward } else if (action == mThumbsDownAction) { // Handle ThumbsDown } else if (action == mThumbsUpAction) { // Handle ThumbsUp } else { // The superclass handles play/pause and delegates next/previous actions to abstract methods, // so those two methods should be overridden rather than handling the actions here. super.onActionClicked(action); } } @Override public void next() { // Skip to next item in playlist. } @Override public void previous() { // Skip to previous item in playlist. }
在特殊情况下,您可能需要实现自己的PlaybackTransportRowPresenter来呈现自定义控件,并使用PlaybackSeekUi响应查找操作。
如果您的应用使用VideoFragment并且您想支持视频清理。
您需要提供PlaybackSeekDataProvider的实现。 此组件提供滚动时使用的视频缩略图。 您必须通过扩展PlaybackSeekDataProvider来实现自己的提供者。 请参阅leanback-showcase应用程序中的示例。