Введите PiP в правильное время

Ваше приложение не должно переходить в режим «картинка в картинке» в следующих ситуациях:

  • Если видео остановлено или поставлено на паузу.
  • Если вы находитесь на другой странице приложения, нежели видеоплеер.

Чтобы контролировать переход вашего приложения в режим «картинка в картинке», добавьте переменную, отслеживающую состояние видеоплеера, используя свойство ` mutableStateOf .

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

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

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

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

Когда игрок отпускается, установите переменную состояния в false :

fun releasePlayer() {
    shouldEnterPipMode = false
}

Используйте состояние для определения того, включен ли режим «картинка в картинке» (до Android 12).

  1. Поскольку добавление PiP до версии 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)