Android 手持設備的畫中畫 (PIP) 功能可讓用戶將正在進行的活動的應用程序調整為小窗口。 PIP 對於視頻應用程序特別有用,因為當用戶可以自由地執行其他操作時,內容會繼續播放。用戶可以通過 SystemUI 操作此窗口的位置,並使用(最多三個)應用程序提供的操作與當前畫中畫的應用程序進行交互。
PIP 需要從支持它的應用程序中明確選擇加入,並在每個活動的基礎上工作。 (單個應用可以有多個activity,其中只有一個是畫中畫。)activity通過調用enterPictureInPictureMode()
請求進入畫中畫,並以onPictureInPictureModeChanged()
的形式接收activity回調。
setPictureInPictureParams()
方法允許活動在 PIP 和自定義操作中控制其縱橫比,這允許用戶與活動交互而無需展開它。在 PIP 中,活動處於暫停但正在渲染的狀態,並且不直接接收觸摸輸入或窗口焦點。一次只能有一個任務在 PIP 中。
Android 開發者畫中畫文檔中提供了更多信息。
設備要求
要支持 PIP,請在/android/frameworks/base/core/java/android/content/pm/PackageManager.java
中啟用PackageManager#FEATURE_PICTURE_IN_PICTURE
系統功能。支持 PIP 的設備的最小寬度必須大於 220dp。與分屏多窗口類似,PIP 允許多個活動同時在屏幕上運行。因此,設備應該有足夠的 CPU 和 RAM 來支持這個用例。
執行
大多數活動生命週期管理是在ActivityManager
和WindowManager
之間的系統中完成的。參考 UI 實現位於SystemUI
包中。
對系統的修改不應影響其由兼容性測試套件 (CTS) 測試定義的內在行為。 PIP 的系統邏輯主要圍繞“固定”堆棧內的任務和活動的管理。這是一個快速的類概述:
-
ActivityRecord
:跟踪每個活動的畫中畫狀態。為了防止用戶在某些情況下(例如從鎖定屏幕或 VR 期間)進入 PIP,請在checkEnterPictureInPictureState()
中添加案例。 -
ActivityManagerService
: Activity請求進入 PIP 的主要接口,以及WindowManager
和SystemUI
調用以更改 PIP 活動狀態的接口。 -
ActivityStackSupervisor
:從ActivityManagerService
調用以將任務移入或移出固定堆棧,並根據需要更新WindowManager
。 -
PinnedStackWindowController
:來自ActivityManager
的WindowManager
接口。 -
PinnedStackController
:向SystemUI
報告系統中的更改,例如 IME 顯示/隱藏、縱橫比更改或操作更改。 -
BoundsAnimationController
:以在調整大小時不會觸發配置更改的方式為 PIP 活動窗口設置動畫。 -
PipSnapAlgorithm
:在系統和 SystemUI 中使用的共享類,用於控制 PIP 窗口靠近屏幕邊緣的捕捉行為。
參考SystemUI
提供了 PIP 的完整實現,支持向用戶呈現自定義操作和一般操作,例如展開和關閉。設備製造商可以在這些更改的基礎上進行構建,只要它們不影響 CDD 定義的內在行為。這是一個快速的類概述:
-
PipManager
:SystemUI
組件,以SystemUI
啟動。 -
PipTouchHandler
:觸摸處理程序,它控制操縱 PIP 的手勢。這僅在 PIP 的輸入使用者處於活動狀態時使用(請參閱InputConsumerController
)。可以在此處添加新手勢。 -
PipMotionHelper
:跟踪 PIP 位置和屏幕上允許區域的便利類。通過調用ActivityManagerService
來更新或動畫 PIP 的位置和大小。 -
PipMenuActivityController
:啟動一個活動,顯示當前在 PIP 中的活動提供的操作。此活動是一個任務覆蓋活動,並刪除了覆蓋輸入使用者以使其具有交互性。 -
PipMenuActivity
:菜單活動的實現。 -
PipMediaController
:當媒體會話以可能影響 PIP 上的默認操作的方式發生變化時更新SystemUI
的偵聽器。 -
PipNotificationController
:確保在用戶使用 PIP 功能時通知處於活動狀態的控制器。 -
PipDismissViewController
:當用戶開始與 PIP 交互時向用戶顯示的覆蓋,以指示它可以被解除。
默認展示位置
有多種系統資源可以控制 PIP 的默認位置:
-
config_defaultPictureInPictureGravity
:重力整數,控制角落放置畫中畫,如BOTTOM|RIGHT
。 -
config_defaultPictureInPictureScreenEdgeInsets
:放置 PIP 的屏幕兩側的偏移量。 -
config_pictureInPictureDefaultSizePercent
和config_pictureInPictureDefaultAspectRatio
:屏幕寬度百分比和縱橫比的組合控制 PIP 的大小。計算的默認 PIP 大小不應小於 CTS 和 CDD 定義的@dimen/default_minimal_size_pip_resizable_task
。 -
config_pictureInPictureSnapMode
:在PipSnapAlgorithm
中定義的捕捉行為。
設備實現不應更改 CDD 和 CTS 中定義的最小和最大縱橫比。
權限
AppOpsManager
( master/core/java/android/app/AppOpsManager.java
) 中的每個包的“應用程序操作”( OP_PICTURE_IN_PICTURE
),允許用戶通過系統設置在每個應用程序級別控制 PIP。當活動請求進入畫中畫模式時,設備實現需要遵守此檢查。
測試
要測試 PIP 實現,請運行在/cts/hostsidetests/services/activitymanager
下的主機端 CTS 測試中找到的所有畫中畫相關測試,特別是在ActivityManagerPinnedStackTests.java
中。