Android O ——— 画中画模式(PIP)初步使用总结
Android O 允许以画中画 (PIP) 模式启动操作组件。PIP 是一种特殊的多窗口模式,最常用于视频播放。目前,PIP 模式可用于 Android TV,而 Android O 则让该功能可进一步用于其他 Android 设备。
当某个 Activity 处于 PIP 模式时,它会处于暂停状态,但仍应继续显示内容。因此,您应确保您的应用在 onPause() 处理程序中进行处理时不会暂停播放。相反,您应在 onStop() 中暂停播放视频,并在 onStart() 中继续播放。如需了解详细信息,请参阅多窗口生命周期。
要指定您的 Activity 可以使用 PIP 模式,请在清单中将 android:supportsPictureInPicture 设置为 true。(从 Android O 开始,如果您打算在 Android TV 或其他 Android 设备上支持 PIP 模式,则无需将 android:resizeableActivity 设置为 true;只有在您的 Activity 支持其他多窗口模式时,才需要设置 android:resizeableActivity。)
多窗口生命周期
多窗口模式不会更改 Activity 生命周期。
在多窗口模式中,在指定时间只有最近与用户交互过的 Activity 为活动状态。 该 Activity 将被视为顶级 Activity。 所有其他 Activity 虽然可见,但均处于暂停状态。 但是,这些已暂停但可见的 Activity 在系统中享有比不可见 Activity 更高的优先级。 如果用户与其中一个暂停的 Activity 交互,该 Activity 将恢复,而之前的顶级 Activity 将暂停。
注:在多窗口模式中,用户仍可以看到处于暂停状态的应用。 应用在暂停状态下可能仍需要继续其操作。 例如,处于暂停模式但可见的视频播放应用应继续显示视频。 因此,我们建议播放视频的 Activity 不要暂停其 onPause() 处理程序中的视频。 应暂停 onStop() 中的视频,并恢复onStart() 中的视频播放。
API 变更
Android O 引入一种新的对象 PictureInPictureParams,您可以将该对象传递给 PIP 函数来指定某个 Activity 在其处于 PIP 模式时的行为。此对象还指定了各种属性,例如操作组件的首选纵横比。
现在,在添加画中画中介绍的现有 PIP 函数可用于所有 Android 设备,而不仅限于 Android TV。此外,Android O 还提供以下函数来支持 PIP 模式:
Activity.enterPictureInPictureMode(PictureInPictureParams args):将操作组件置于画中画模式。操作组件的纵横比和其他配置设置均由 args 指定。如果 args 中的任何字段为空,系统将使用您上次调用 Activity.setPictureInPictureParams()时所设置的值。
指定的操作组件被置于屏幕的一角,屏幕剩余部分则被屏幕显示的上一个操作组件填满。进入 PIP 模式的 Activity 将进入暂停状态,但仍保持已启动状态。如果用户点按此 PIP 操作组件,系统将显示一个菜单供用户操作,而在操作组件处于 PIP 状态期间,不会理会任何触摸事件。
Activity.setPictureInPictureParams():更新操作组件的 PIP 配置设置。如果操作组件目前处于 PIP 模式,则会更新此设置;如果操作组件的纵横比发生变化,这非常有用。如果操作组件不处于 PIP 模式,则会使用这些配置设置,而不会考虑您调用的 enterPictureInPictureMode() 函数。
画中画 Demo示例
您的应用可以决定何时触发 PIP 模式。以下是一些关于何时进入 PIP 模式的示例:
- 当用户从视频返回浏览其他内容时,应用将自动进入 PIP 模式。
- 当用户快看完一集视频时,应用将视频切换到 PIP 模式。
- 主屏幕显示有关该系列视频下一集的宣传或摘要信息。
- 应用将允许用户在观看视频的同时添加其他内容到队列。 视频继续在 PIP 模式中播放,同时主屏幕显示内容选择 Activity。
PIP 窗口为 240x135 dp,在屏幕角落的最顶层显示,由系统在四个角落中选择一个角落。 用户可以调出 PIP 菜单,将 PIP 窗口切换为全屏,或通过按下遥控器上的主页按钮关闭 PIP 窗口。 如果主屏幕开始播放另一个视频,PIP 窗口将自动关闭。 用户还可以通过“最近使用记录”关闭 PIP 窗口。
图 1. 用户在主屏幕上浏览内容时屏幕角落窗口播放画中画视频。PIP 利用 Android N 中提供的多窗口 API 显示固定视频层叠窗口。 如需将 PIP 添加到应用,您需要注册支持 PIP 的 Activity,然后根据需要将 Activity 切换到 PIP 模式,并确保隐藏所有 UI 元素,且 Activity 处于 PIP 模式时视频继续播放。
声明您的 Activity 支持画中画
默认情况下,系统并不自动为应用提供 PIP 支持。如果想要应用支持 PIP,请将 android:supportsPictureInPicture 和 android:resizeableActivity 设置为 true,在清单中注册视频 Activity。 此外,应明确指定 Activity 处理布局配置变更,这样,在 PIP 模式过渡期间发生布局变更时,Activity 不会重新启动。
<activity android:name="VideoActivity"
android:resizeableActivity="true"
android:supportsPictureInPicture="true"
android:configChanges=
"screenSize|smallestScreenSize|screenLayout|orientation"
...
在注册 Activity 时,请记住,在 PIP 模式中,您的 Activity 在电视屏幕上的小层叠窗口中显示。 视频播放 Activity 结合以尽量小的 UI 可以实现最佳用户体验。 在切换到 PIP 模式后,UI 元素较小的 Activity 带来的用户体验可能较差,因为用户在 PIP 窗口中看不到 UI 元素的详细信息。
将您的 Activity 切换到画中画模式
在需要将 Activity 切换到 PIP 模式时,请调用 Activity.enterPictureInPictureMode()。在下面的示例中,当用户选择媒体控制栏上的专用 PIP 按钮时,系统切换到 PIP 模式:
@Override
public void onActionClicked(Action action) {
if (action.getId() == R.id.lb_control_picture_in_picture) {
getActivity().enterPictureInPictureMode();
return;
}
...
在媒体控制栏上添加 PIP 按钮可以方便用户在控制视频播放的同时切换到 PIP 模式。
图 1. 媒体控制栏上的画中画按钮。Android N 中包含一个新的 PlaybackControlsRow.PictureInPictureAction 类,它可以定义控制栏 PIP 操作并使用 PIP 图标。
处理画中画模式中的 UI
在 Activity 进入 PIP 模式时,Activity 应仅显示视频播放。 在 Activity 进入 PIP 模式前删除 UI 元素,当 Activity 再次全屏显示时恢复这些元素。重写 Activity.onPictureInPictureModeChanged() 或 Fragment.onPictureInPictureModeChanged(),并根据需要启用或禁用 UI 元素,例如:
@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
if (isInPictureInPictureMode) {
// Hide the controls in picture-in-picture mode.
...
} else {
// Restore the playback UI based on the playback status.
...
}
}
在画中画模式中继续视频播放
在 Activity 切换到 PIP 模式时,系统会认为 Activity 处于暂停状态,并调用 Activity 的 onPause() 方法。 如果 Activity 因为 PIP 模式暂停,视频播放不应暂停,而是应继续播放。 在 Activity 的 onPause() 方法中检查 PIP,并对播放做相应处理,例如:
@Override
public void onPause() {
// If called while in PIP mode, do not pause playback
if (isInPictureInPictureMode()) {
// Continue playback
...
}
// If paused but not in PIP, pause playback if necessary
...
}
当 Activity 退出 PIP 模式并回到全屏模式时,系统会恢复 Activity 并调用 onResume() 方法。
使用画中画的单次播放 Activity
在您的应用中,用户可以在浏览主屏幕中的内容时选择一个新的视频,视频播放 Activity 处于 PIP 模式。 在现有播放 Activity 中全屏模式下播放新视频,而不是启用可能使用户感到困惑的新 Activity。
若要确保视频播放请求使用的是单个 Activity 并根据需要进入或退出 PIP 模式,在您的清单中将 Activity 的 android:launchMode 设置为 singleTask:
<activity android:name="VideoActivity"
...
android:supportsPictureInPicture="true"
android:launchMode="singleTask"
...
在您的 Activity 中,替换 Activity.onNewIntent(),处理新视频,如果需要,停止任何现有视频播放。
最佳做法
PIP 用于全屏播放视频的 Activity。在 Activity 切换到 PIP 模式时,应避免显示除视频外的其他内容。根据处理画中画模式中的 UI 中所述,在 Activity 进入 PIP 模式时进行跟踪,并隐藏 UI 元素。
由于 PIP 窗口悬浮在屏幕的角落,因此应避免在主窗口被 PIP 窗口遮挡的任何区域显示重要信息。
当 Activity 处于 PIP 模式时,其默认不获取输入焦点。要在 PIP 模式中接收输入事件,请使用 MediaSession.setMediaButtonReceiver()。