自 2025 年 3 月 27 日起,我们建议您使用 android-latest-release
而非 aosp-main
构建 AOSP 并为其做出贡献。如需了解详情,请参阅 AOSP 的变更。
画中画
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
借助 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
。
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-03-26。
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["没有我需要的信息","missingTheInformationINeed","thumb-down"],["太复杂/步骤太多","tooComplicatedTooManySteps","thumb-down"],["内容需要更新","outOfDate","thumb-down"],["翻译问题","translationIssue","thumb-down"],["示例/代码问题","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-03-26。"],[],[],null,["# Picture-in-picture\n\nThe picture-in-picture (PIP) feature for Android handheld devices lets users resize an app with an\nongoing activity into a small window. PIP is especially useful for video apps because content\ncontinues to play while the user is free to perform other actions. Users can manipulate this\nwindow's position through the SystemUI and interact with the application currently\nin picture-in-picture with (up to three) app-provided actions.\n\n\nPIP requires explicit opt-in from applications that support it and works on a\nper-activity basis. (A single application can have multiple activities, only one\nof which is in PIP.) Activities request to enter picture-in-picture by calling\n`enterPictureInPictureMode()`, and receive activity callbacks in the\nform of `onPictureInPictureModeChanged()`.\n\n\nThe `setPictureInPictureParams()` method lets activities control their\naspect ratio while in PIP and custom actions, which allow users to interact with\nthe activity without having to expand it. In PIP, the activity is in a paused,\nbut rendering, state and doesn't directly receive touch input or window focus.\nOnly a single task can be in PIP at a time.\n\n\nMore information is available in the Android Developer\n[Picture-in-picture](https://developer.android.com/training/tv/playback/picture-in-picture.html)\ndocumentation.\n\nDevice requirements\n-------------------\n\n\nTo support PIP, enable the\n`PackageManager#FEATURE_PICTURE_IN_PICTURE` system feature in\n[/android/frameworks/base/core/java/android/content/pm/PackageManager.java](https://android.googlesource.com/platform/frameworks/base/+/android16-release/core/java/android/content/pm/PackageManager.java).\nDevices that support PIP must have a screen that is larger than 220dp at its\nsmallest width. Similar to split screen multi-window, PIP allows multiple\nactivities to run on-screen at the same time. Therefore, devices should have\nsufficient CPU and RAM to support this use case.\n\nImplementation\n--------------\n\n\nMost of the activity lifecycle management is done in system between\n[ActivityManager](https://android.googlesource.com/platform/frameworks/base/+/android16-release/services/core/java/com/android/server/am/) and [WindowManager](https://android.googlesource.com/platform/frameworks/base/+/android16-release/services/core/java/com/android/server/wm/).\nThe reference UI implementation is in the [SystemUI](https://android.googlesource.com/platform/frameworks/base/+/android16-release/packages/SystemUI/)\npackage.\n\n\nModifications to the system should not affect its intrinsic behavior as defined\nby the [Compatibility Test Suite (CTS) tests](#cts-tests).\nThe system logic for PIP mainly revolves around the management of tasks and\nactivities within the \"pinned\" stack. Here is a quick class overview:\n\n- **`ActivityRecord`:** tracks each activity's picture-in-picture state. To prevent users from entering PIP in certain circumstances, such as from the lock screen or during VR, add cases to `checkEnterPictureInPictureState()`.\n- **`ActivityManagerService`:** the primary interface from the activity to request entering PIP and the interface to calls from `WindowManager` and `SystemUI` to change the PIP activity state.\n- **`ActivityStackSupervisor`:** called from the `ActivityManagerService` to move tasks in or out of the pinned stack, updating the `WindowManager` as necessary.\n- **`PinnedStackWindowController`:** the `WindowManager` interface from `ActivityManager`.\n- **`PinnedStackController`:** reports changes in the system to `SystemUI`, such as IME shown/hidden, aspect ratio changed, or actions changed.\n- **`BoundsAnimationController`:** animates the PIP activity windows in a way that does not trigger a configuration change while resizing.\n- **`PipSnapAlgorithm`:** a shared class used in both the system and SystemUI that controls the snapping behaviour of the PIP window near the edges of the screen.\n\n\nThe reference [SystemUI](https://android.googlesource.com/platform/frameworks/base/+/android16-release/packages/SystemUI/)\nprovides a complete implementation of PIP that supports presenting custom\nactions to users and general manipulation, such as expansion and dismissal.\nDevice manufacturers can build upon these changes, as long as they do not affect\nthe intrinsic behaviours as defined by the CDD. Here is a quick class\noverview:\n\n- **`PipManager`:** the `SystemUI` component that is started with `SystemUI`.\n- **`PipTouchHandler`:** the touch handler, which controls the gestures that manipulate the PIP. This is only used while the input consumer for the PIP is active (see `InputConsumerController`). New gestures can be added here.\n- **`PipMotionHelper`:** a convenience class that tracks the PIP position, and allowable region on-screen. Calls through to `ActivityManagerService` to update or animate the position and size of the PIP.\n- **`PipMenuActivityController`:** starts an activity that shows the actions provided by the activity currently in PIP. This activity is a task-overlay activity, and removes the overlaying input consumer to allow it to be interactive.\n- **`PipMenuActivity`:** the implementation for the menu activity.\n- **`PipMediaController`:** the listener that updates `SystemUI` when the media session changes in a way that might affect the default actions on the PIP.\n- **`PipNotificationController`:** the controller that ensures that a notification is active while a user is using the PIP feature.\n- **`PipDismissViewController`:** the overlay shown to users when they start interacting with the PIP to indicate that it can be dismissed.\n\nDefault placement\n-----------------\n\n\nThere are various system resources that control the default placement of the\nPIP:\n\n- **`config_defaultPictureInPictureGravity`:** the [gravity](https://developer.android.com/reference/android/view/Gravity.html) integer, which controls the corner to place the PIP, such as `BOTTOM|RIGHT`.\n- **`config_defaultPictureInPictureScreenEdgeInsets`:** the offsets from the sides of the screen to place the PIP.\n- **`config_pictureInPictureDefaultSizePercent` and\n `config_pictureInPictureDefaultAspectRatio`:** the combination of percentage of the screen width and the aspect ratio controls the size of the PIP. The computed default PIP size should not be smaller than `@dimen/default_minimal_size_pip_resizable_task`, as defined by CTS and the CDD.\n- **`config_pictureInPictureSnapMode`:** the snapping behaviour as defined in `PipSnapAlgorithm`.\n\n\nDevice implementations should not change the minimum and maximum aspect ratios\nthat are defined in the CDD and CTS.\n\nPermissions\n-----------\n\n\nThe per-package \"application operation\"\n(`OP_PICTURE_IN_PICTURE`) in `AppOpsManager`\n(`main/core/java/android/app/AppOpsManager.java`), lets\nusers to control PIP on a per-application level through the system settings.\nDevice implementations need to respect this check when an activity requests to\nenter picture-in-picture mode.\n\nTesting\n-------\n\n\nTo test PIP implementations, run all picture-in-picture related tests found in\nthe host-side CTS tests under [/cts/hostsidetests/services/activitymanager](https://android.googlesource.com/platform/cts/+/android16-release/hostsidetests/services/activitymanager/src/android/server/cts),\nparticularly in `ActivityManagerPinnedStackTests.java`."]]