借助 Android 手持设备的画中画 (PIP) 功能,用户可以将当前正在运行 activity 的应用缩到小窗口中显示。画中画对视频应用来说尤其有用,因为用户可以随时执行其他操作,不必打断内容播放。用户可以通过 SystemUI 操控该窗口的位置,并通过应用提供的操作(最多三项)与当前处于画中画模式的应用流畅地互动。
画中画功能需要在支持它的应用中明确选择启用,并按 activity 运作(一个应用可以有多个 activity,但其中只有一个可处于画中画模式)。Activity 通过调用 enterPictureInPictureMode()
请求以进入画中画模式,并以 onPictureInPictureModeChanged()
的形式接收 Activity 回调。
setPictureInPictureParams()
方法可让 activity 控制其在画中画模式下的宽高比和自定义操作,这样一来,用户无需展开 activity 便可以与之互动。在画中画模式下,activity 处于暂停但继续呈现的状态,并且不直接接收触摸输入或窗口焦点。在同一时间点,只能有一项任务处于画中画模式。
如需了解详情,请参阅 Android 开发者画中画文档。
设备要求
要支持画中画功能,请在 /android/frameworks/base/core/java/android/content/pm/PackageManager.java
中启用 PackageManager#FEATURE_PICTURE_IN_PICTURE
系统功能。支持画中画功能的设备的最小屏幕宽度必须大于 220dp。与分屏多窗口类似,画中画功能支持多个 activity 同时在屏幕上运行。因此,设备的 CPU 和 RAM 要足以支持这类使用情形。
实现
大多数 activity 生命周期管理都发生在 ActivityManager
和 WindowManager
系统中。参考界面实现位于 SystemUI
软件包中。
对系统所做的修改不应影响其内在行为(如兼容性测试套件 (CTS) 测试中所定义)。画中画功能的系统逻辑主要围绕“置顶”堆栈中的任务和 activity 管理而展开。以下是对系统逻辑类的简单介绍:
ActivityRecord
:跟踪每个 activity 的画中画状态。为了防止用户在某些情况下(例如从锁定屏幕或在 VR 中)进入画中画,请向checkEnterPictureInPictureState()
添加相应用例。ActivityManagerService
:activity 在请求进入画中画模式时所调用的主接口,也是WindowManager
和SystemUI
更改画中画 activity 状态时所调用的接口。ActivityStackSupervisor
:从ActivityManagerService
调用以将任务移入或移出固定的堆栈,并根据需要更新WindowManager
。PinnedStackWindowController
:来自ActivityManager
的WindowManager
接口。PinnedStackController
:将系统中的更改报告给SystemUI
,例如 IME 显示/隐藏、宽高比已更改或操作发生变化。BoundsAnimationController
:以不触发配置更改(在调整大小的过程中)的方式,对画中画 Activity 窗口进行动画处理。PipSnapAlgorithm
:系统和 SystemUI 中使用的共享类,可控制屏幕边缘附近的画中画窗口的贴靠行为。
参考 SystemUI
提供画中画功能的完整实现(支持向用户呈现自定义操作并执行展开和关闭等常规操作)。设备制造商可以在这些变更的基础上进行构建,只要它们不影响 CDD 定义的内在行为即可。以下是对系统逻辑类的简单介绍:
PipManager
:以SystemUI
开头的SystemUI
组件。PipTouchHandler
:触摸处理程序,用于控制操控画中画的手势。只有在画中画的处于活动状态的用户处于此状态时,才使用此属性(请参阅InputConsumerController
)。可在此添加新手势。PipMotionHelper
:一个辅助类,用于跟踪画中画的位置和屏幕上允许的区域。通过调用ActivityManagerService
来更新画中画,或调整画中画的位置和大小。PipMenuActivityController
:启动一个 Activity,以显示当前画中画中的 Activity 提供的操作。此 activity 是任务叠加层 activity,并移除叠加输入使用方,使其处于互动状态。PipMenuActivity
:菜单 Activity 的实现。PipMediaController
:当媒体会话以可能影响画中画的默认操作的方式发生变化时更新SystemUI
的监听器。PipNotificationController
:确保在用户使用画中画功能时显示一条通知的控制器。PipDismissViewController
:当用户开始与画中画互动时向用户显示的叠加层,以表明用户可以关闭画中画。
默认显示位置
用于控制画中画的默认显示位置的系统资源有多项:
config_defaultPictureInPictureGravity
:重力整数,用于控制放置画中画的角落,例如BOTTOM|RIGHT
。config_defaultPictureInPictureScreenEdgeInsets
:放置画中画的位置与屏幕侧边的偏移量。config_pictureInPictureDefaultSizePercent
和config_pictureInPictureDefaultAspectRatio
:屏幕宽度的百分比和宽高比的组合控制画中画的大小。根据 CTS 和 CDD 的定义,计算的默认画中画大小不得小于@dimen/default_minimal_size_pip_resizable_task
。config_pictureInPictureSnapMode
:PipSnapAlgorithm
中定义的贴靠行为。
设备实现不应更改 CDD 和 CTS 中定义的宽高比上限和下限。
权限
AppOpsManager
(main/core/java/android/app/AppOpsManager.java
) 中的基于软件包的“应用操作”(OP_PICTURE_IN_PICTURE
),可让用户通过系统设置在应用级别控制画中画。当 activity 请求进入画中画模式时,设备实现需要遵循此检查要求。
测试
如需测试画中画实现,请在 /cts/hostsidetests/services/activitymanager
下的主机端 CTS 测试中找到所有与画中画相关的测试,尤其是 ActivityManagerPinnedStackTests.java
。