Android 手持裝置的畫中畫 (PIP) 功能可讓使用者將正在進行的活動的應用程式調整到小視窗中。 PIP 對於視訊應用程式特別有用,因為當使用者可以自由執行其他操作時,內容會繼續播放。使用者可以透過 SystemUI 操縱此視窗的位置,並使用(最多三個)應用程式提供的操作與目前處於畫中畫狀態的應用程式互動。
PIP 需要支援它的應用程式明確選擇加入,並且基於每個活動進行工作。 (單一應用程式可以有多個 Activity,其中只有一個處於 PIP 模式。)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
:請求進入 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
( main/core/java/android/app/AppOpsManager.java
) 中的每個套件「應用程式操作」( OP_PICTURE_IN_PICTURE
) 允許使用者透過系統設定在每個應用程式層級上控制 PIP。當活動請求進入畫中畫模式時,設備實作需要遵守此檢查。
測試
若要測試 PIP 實現,請執行/cts/hostsidetests/services/activitymanager
下的主機端 CTS 測試中找到的所有畫中畫相關測試,特別是在ActivityManagerPinnedStackTests.java
中。