Wprowadzanie PiP we właściwych momentach

W tych sytuacjach aplikacja nie powinna przechodzić w tryb obrazu w obrazie:

  • Gdy film jest zatrzymany lub wstrzymany.
  • Gdy jesteś na innej stronie aplikacji niż odtwarzacz wideo.

Aby kontrolować, kiedy aplikacja przechodzi w tryb obrazu w obrazie, dodaj zmienną, która śledzi stan odtwarzacza wideo za pomocą funkcji mutableStateOf.

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

Aby przełączać stan w zależności od tego, czy odtwarzacz wideo jest odtwarzany, dodaj do niego detektor. Przełącz stan zmiennej stanu w zależności od tego, czy odtwarzacz jest odtwarzany:

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

Przełączanie stanu w zależności od tego, czy odtwarzacz jest zwolniony

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

fun releasePlayer() {
    shouldEnterPipMode = false
}

Używanie stanu do określania, czy należy przejść w tryb obrazu w obrazie (wersje Androida starsze niż 12)

  1. Ponieważ dodanie trybu obrazu w obrazie w wersjach starszych niż 12 wymaga użycia funkcji DisposableEffect, musisz utworzyć nową zmienną za pomocą funkcji rememberUpdatedState, w której newValue jest ustawiona jako zmienna stanu. Dzięki temu w funkcji DisposableEffect będzie używana zaktualizowana wersja.
  2. W lambdzie, która określa działanie po wywołaniu funkcji OnUserLeaveHintListener, dodaj instrukcję if ze zmienną stanu wokół wywołania funkcji 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 należy przejść w tryb obrazu w obrazie (wersje Androida nowsze niż 12)

Przekaż zmienną stanu do funkcji 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)

Używanie funkcji setSourceRectHint do tworzenia płynnej animacji

Interfejs API setSourceRectHint tworzy płynniejszą animację przejścia w tryb obrazu w obrazie. W Androidzie 12 i nowszych wersjach tworzy też płynniejszą animację wyjścia z trybu obrazu w obrazie. Dodaj ten interfejs API do narzędzia do tworzenia trybu obrazu w obrazie, aby wskazać obszar aktywności widoczny po przejściu w tryb obrazu w obrazie.

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