Переход в режим "Картинка в картинке" в нужное время

Приложение не должно переходить в режим "Картинка в картинке" в следующих случаях:

  • Видео остановлено или приостановлено.
  • Если вы находитесь не на странице с видеопроигрывателем.

Чтобы контролировать, когда приложение переходит в режим "Картинка в картинке", добавьте переменную, которая отслеживает состояние видеопроигрывателя с помощью mutableStateOf.

Переключать состояние в зависимости от того, воспроизводится ли видео

Чтобы переключать состояние в зависимости от того, воспроизводится ли видео, добавьте прослушиватель в видеопроигрыватель. Переключайте состояние переменной в зависимости от того, играет ли пользователь:

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

Переключать состояние в зависимости от того, выпущен ли проигрыватель

Когда проигрыватель освобождается, задайте для переменной состояния значение false:

fun releasePlayer() {
    shouldEnterPipMode = false
}

Используйте состояние, чтобы определить, включен ли режим "Картинка в картинке" (для версий до Android 12)

  1. Поскольку для добавления режима "Картинка в картинке" в версиях до Android 12 используется DisposableEffect, вам нужно создать новую переменную с помощью rememberUpdatedState, указав newValue в качестве переменной состояния. Это позволит использовать обновленную версию в DisposableEffect.
  2. В лямбда-выражении, которое определяет поведение при срабатывании OnUserLeaveHintListener, добавьте оператор if с переменной состояния вокруг вызова enterPictureInPictureMode():

    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 для плавной анимации

API setSourceRectHint делает анимацию перехода в режим "картинка в картинке" более плавной. В Android 12 и более поздних версиях это также делает анимацию выхода из режима "Картинка в картинке" более плавной. Добавьте этот API в конструктор PiP, чтобы указать область действия, которая видна после перехода в режим "картинка в картинке".

  1. Добавляйте setSourceRectHint() в builder, только если состояние определяет, что приложение должно перейти в режим "Картинка в картинке". Это позволяет избежать вычисления sourceRect, когда приложению не нужно переходить в режим "Картинка в картинке".
  2. Чтобы задать значение sourceRect, используйте layoutCoordinates, полученные из функции onGloballyPositioned в модификаторе.
  3. Вызовите метод setSourceRectHint() для объекта builder и передайте ему переменную 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)