設定應用程式以使用子母畫面模式

AndroidManifest.xml 檔案的活動標記中,執行下列操作:

  1. 新增 supportsPictureInPicture 並將其設為 true,宣告您將在應用程式中使用 PiP。
  2. 新增 configChanges 並將其設為 orientation|screenLayout|screenSize|smallestScreenSize,指定活動會處理版面配置設定變更。這樣一來,如果版面配置在子母畫面模式轉換期間有所變更,活動就不會重新啟動。

      <activity
        android:name=".SnippetsActivity"
        android:exported="true"
        android:supportsPictureInPicture="true"
        android:configChanges="orientation|screenLayout|screenSize|smallestScreenSize"
        android:theme="@style/Theme.Snippets">

在 Compose 程式碼中執行下列操作:

  1. Context 中新增這個擴充功能。您將在指南中多次使用這項擴充功能來存取活動。
    internal fun Context.findActivity(): ComponentActivity {
        var context = this
        while (context is ContextWrapper) {
            if (context is ComponentActivity) return context
            context = context.baseContext
        }
        throw IllegalStateException("Picture in picture should be called in the context of an Activity")
    }

在 Android 12 以下版本中新增離開應用程式時的 PiP

如要為 Android 12 以下版本新增子母畫面,請使用 addOnUserLeaveHintProvider。如要為 Android 12 以下版本新增 PiP,請按照下列步驟操作:

  1. 新增版本閘道,讓這段程式碼只在 O 到 R 版本中存取。
  2. 使用 DisposableEffect,並以 Context 做為鍵。
  3. DisposableEffect 中,定義使用 lambda 觸發 onUserLeaveHintProvider 時的行為。在 lambda 中,對 findActivity() 呼叫 enterPictureInPictureMode(),並傳入 PictureInPictureParams.Builder().build()
  4. 使用 findActivity() 新增 addOnUserLeaveHintListener,並傳入 lambda。
  5. onDispose 中,使用 findActivity() 新增 removeOnUserLeaveHintListener,並傳入 lambda。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
    Build.VERSION.SDK_INT < Build.VERSION_CODES.S
) {
    val context = LocalContext.current
    DisposableEffect(context) {
        val onUserLeaveBehavior: () -> Unit = {
            context.findActivity()
                .enterPictureInPictureMode(PictureInPictureParams.Builder().build())
        }
        context.findActivity().addOnUserLeaveHintListener(
            onUserLeaveBehavior
        )
        onDispose {
            context.findActivity().removeOnUserLeaveHintListener(
                onUserLeaveBehavior
            )
        }
    }
} else {
    Log.i("PiP info", "API does not support PiP")
}

在 Android 12 之後的版本中新增離開應用程式時的 PiP

在 Android 12 之後,PictureInPictureParams.Builder 會透過傳遞至應用程式影片播放器的修飾符新增。

  1. 建立 modifier,並呼叫其上的 onGloballyPositioned。稍後的步驟會使用版面配置座標。
  2. PictureInPictureParams.Builder() 建立變數。
  3. 新增 if 陳述式,檢查 SDK 是否為 S 以上版本。如果是,請將 setAutoEnterEnabled 新增至建構工具,並將其設為 true,以便在滑動時進入 PiP 模式。這比透過 enterPictureInPictureMode 提供更流暢的動畫。
  4. 使用 findActivity() 呼叫 setPictureInPictureParams()。對 builder 呼叫 build(),然後傳入。

val pipModifier = modifier.onGloballyPositioned { layoutCoordinates ->
    val builder = PictureInPictureParams.Builder()

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        builder.setAutoEnterEnabled(true)
    }
    context.findActivity().setPictureInPictureParams(builder.build())
}
VideoPlayer(pipModifier)

使用 setAspectRatio 設定子母畫面視窗的顯示比例

如要設定 PiP 視窗的顯示比例,您可以選擇特定的顯示比例,也可以使用播放器影片大小的寬度和高度。如果您使用 media3 播放器,請先確認播放器不為空值,且播放器的影片大小不等於 [VideoSize.UNKNOWN][6],再設定顯示比例。

val context = LocalContext.current

val pipModifier = modifier.onGloballyPositioned { layoutCoordinates ->
    val builder = PictureInPictureParams.Builder()
    if (shouldEnterPipMode && player != null && player.videoSize != VideoSize.UNKNOWN) {
        val sourceRect = layoutCoordinates.boundsInWindow().toAndroidRectF().toRect()
        builder.setSourceRectHint(sourceRect)
        builder.setAspectRatio(
            Rational(player.videoSize.width, player.videoSize.height)
        )
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        builder.setAutoEnterEnabled(shouldEnterPipMode)
    }
    context.findActivity().setPictureInPictureParams(builder.build())
}

VideoPlayer(pipModifier)

如果您使用的是自訂播放器,請使用播放器專屬的語法,設定播放器的高度和寬度的顯示比例。請注意,如果播放器在初始化期間調整大小,且超出可用的顯示比例邊界,應用程式就會當機。您可能需要新增檢查項目,以便計算顯示比例,類似於 media3 播放器的做法。