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

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 之前的版本)

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

  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 = Runnable {
            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 以上版本)

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

  1. 建立 modifier,並對其呼叫 onGloballyPositioned。版面配置座標會在後續步驟中使用。
  2. 建立 PictureInPictureParams.Builder() 的變數。
  3. 新增 if 陳述式,檢查 SDK 是否為 S 以上版本。如果是,請將 setAutoEnterEnabled 新增至建構工具,並設為 true,以便在滑動時進入子母畫面模式。與透過 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 設定子母畫面視窗的顯示比例

如要設定子母畫面視窗的顯示比例,你可以選擇特定顯示比例,或使用播放器影片大小的寬度和高度。如果您使用 media3 播放器,請先檢查播放器是否不為空值,以及播放器的影片大小是否不等於 VideoSize.UNKNOWN,再設定顯示比例。

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 播放器類似。