Wprowadzanie PiP we właściwych momentach

Aplikacja nie powinna przechodzić w tryb obrazu w obrazie w tych sytuacjach:

  • Jeśli film zostanie zatrzymany lub wstrzymany.
  • Jeśli jesteś na innej stronie aplikacji niż odtwarzacz.

Aby kontrolować, kiedy aplikacja przechodzi w tryb obrazu w obrazie, dodaj zmienną, która śledzi stan odtwarzacza, używając mutableStateOf.

Przełącz stan w zależności od tego, czy film jest odtwarzany

Aby przełączać stan w zależności od tego, czy odtwarzacz odtwarza film, dodaj detektor do odtwarzacza. Przełącz stan zmiennej stanu w zależności od tego, czy odtwarzacz odtwarza treści:

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

Przełącz stan w zależności od tego, czy odtwarzacz został zwolniony

Gdy odtwarzacz zostanie zwolniony, ustaw zmienną stanu na false:

fun releasePlayer() {
    shouldEnterPipMode = false
}

Używanie stanu do określania, czy tryb obrazu w obrazie jest włączony (Android 11 i starsze)

  1. Ponieważ dodanie PiP przed wersją 12 wymaga użycia DisposableEffect, musisz utworzyć nową zmienną, rememberUpdatedState, ze zmienną stanu ustawioną na newValue. Dzięki temu zaktualizowana wersja będzie używana w DisposableEffect.
  2. W wyrażeniu lambda, które definiuje zachowanie po aktywowaniu OnUserLeaveHintListener, dodaj instrukcję if ze zmienną stanu wokół wywołania 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")
    }

Używanie stanu do określania, czy tryb obrazu w obrazie jest włączony (Android 12 i nowsze)

Przekaż zmienną stanu do setAutoEnterEnabled, aby aplikacja przechodziła w tryb obrazu w obrazie tylko w odpowiednim momencie:

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)

Aby uzyskać płynną animację, użyj setSourceRectHint

Interfejs API setSourceRectHint tworzy płynniejszą animację podczas przechodzenia do trybu obrazu w obrazie. W Androidzie 12 i nowszych wersjach zapewnia też płynniejszą animację podczas wychodzenia z trybu obrazu w obrazie. Dodaj ten interfejs API do kreatora obrazu w obrazie, aby wskazać obszar aktywności, który jest widoczny po przejściu do trybu obrazu w obrazie.

  1. Dodaj setSourceRectHint() do builder tylko wtedy, gdy stan określa, że aplikacja powinna przejść w tryb obrazu w obrazie. Dzięki temu nie trzeba obliczać sourceRect, gdy aplikacja nie musi przechodzić w tryb obrazu w obrazie.
  2. Aby ustawić wartość sourceRect, użyj wartości layoutCoordinates podanych przez funkcję onGloballyPositioned w modyfikatorze.
  3. Wywołaj setSourceRectHint() na builder i przekaż zmienną 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)