適切なタイミングで PiP に入る

次のような状況では、アプリを PiP モードに切り替えないでください。

  • 動画が停止または一時停止されている場合。
  • 動画プレーヤーとは異なるアプリのページにいる場合。

アプリがピクチャー イン ピクチャー モードに切り替わるタイミングを制御するには、mutableStateOf を使用して動画プレーヤーの状態を追跡する変数を追加します。

動画が再生されているかどうかに基づいて状態を切り替える

動画プレーヤーが再生中かどうかに基づいて状態を切り替えるには、動画プレーヤーにリスナーを追加します。プレーヤーが再生中かどうかに基づいて、状態変数の状態を切り替えます。

player.addListener(object : Player.Listener {
    override fun onIsPlayingChanged(isPlaying: Boolean) {
        shouldEnterPipMode = isPlaying
    }
})

プレーヤーが解放されているかどうかに基づいて状態を切り替える

プレーヤーが解放されたら、状態変数を false に設定します。

fun releasePlayer() {
    shouldEnterPipMode = false
}

状態を使用して、PiP モードに入るかどうかを定義する(Android 12 より前)

  1. Android 12 より前のバージョンで PiP を追加するには DisposableEffect を使用するため、newValue を状態変数として設定した rememberUpdatedState で新しい変数を作成する必要があります。これにより、更新されたバージョンが DisposableEffect 内で使用されます。
  2. OnUserLeaveHintListener がトリガーされたときの動作を定義するラムダで、enterPictureInPictureMode() の呼び出しを囲む状態変数を含む if ステートメントを追加します。

    val currentShouldEnterPipMode by rememberUpdatedState(newValue = shouldEnterPipMode)
    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 {
                if (currentShouldEnterPipMode) {
                    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 以降)

アプリが適切なタイミングでのみピクチャー イン ピクチャー モードに移行するように、状態変数を setAutoEnterEnabled に渡します。

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

    // Add autoEnterEnabled for versions S and up
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        builder.setAutoEnterEnabled(shouldEnterPipMode)
    }
    context.findActivity().setPictureInPictureParams(builder.build())
}

VideoPlayer(pipModifier)

スムーズなアニメーションには setSourceRectHint を使用する

setSourceRectHint API を使用すると、ピクチャー イン ピクチャー モードに切り替える際のアニメーションがスムーズになります。Android 12 以降では、ピクチャー イン ピクチャー モードを終了する際のアニメーションもスムーズになります。 この API を PiP ビルダーに追加して、PiP への移行後に表示されるアクティビティの領域を指定します。

  1. アプリがピクチャー イン ピクチャー モードに移行する必要があることを状態が定義している場合にのみ、setSourceRectHint() を builder に追加します。これにより、アプリが PiP に入る必要がない場合に sourceRect が計算されるのを回避できます。
  2. sourceRect 値を設定するには、修飾子の onGloballyPositioned 関数から提供される layoutCoordinates を使用します。
  3. builder に対して setSourceRectHint() を呼び出し、sourceRect 変数を渡します。

val context = LocalContext.current

val pipModifier = modifier.onGloballyPositioned { layoutCoordinates ->
    val builder = PictureInPictureParams.Builder()
    if (shouldEnterPipMode) {
        val sourceRect = layoutCoordinates.boundsInWindow().toAndroidRectF().toRect()
        builder.setSourceRectHint(sourceRect)
    }

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

VideoPlayer(pipModifier)