Inserire il PiP nei momenti corretti

L'app non deve entrare in modalità PiP nelle seguenti situazioni:

  • Se il video è fermo o in pausa.
  • Se non sei nella pagina del video player dell'app.

Per controllare quando l'app entra in modalità PiP, aggiungi una variabile che monitori lo stato del video player utilizzando un mutableStateOf.

Attiva/disattiva lo stato in base alla riproduzione del video

Per attivare/disattivare lo stato in base alla riproduzione del video player, aggiungi un ascoltatore sul video player. Attiva/disattiva lo stato della variabile di stato in base al fatto che il giocatore sia o meno in riproduzione:

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

Attiva/disattiva lo stato in base al rilascio del giocatore

Quando il player viene rilasciato, imposta la variabile di stato su false:

fun releasePlayer() {
    shouldEnterPipMode = false
}

Utilizza lo stato per definire se è stata attivata la modalità PiP (versioni precedenti ad Android 12)

  1. Poiché l'aggiunta di PiP prima della versione 12 utilizza un DisposableEffect, devi creare una nuova variabile tramite rememberUpdatedState con newValue impostato come variabile di stato. In questo modo, la versione aggiornata verrà utilizzata in DisposableEffect.
  2. Nella funzione lambda che definisce il comportamento quando viene attivato OnUserLeaveHintListener, aggiungi un'istruzione if con la variabile di stato intorno alla chiamata a 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: () -> Unit = {
                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")
    }

Utilizza lo stato per definire se è stata attivata la modalità PiP (dopo Android 12)

Passa la variabile di stato a setAutoEnterEnabled in modo che l'app entri in modalità PiP solo al momento giusto:

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)

Utilizza setSourceRectHint per implementare un'animazione fluida

L'API setSourceRectHint crea un'animazione più fluida per accedere alla modalità PiP. In Android 12 e versioni successive, crea anche un'animazione più fluida per uscire dalla modalità PiP. Aggiungi questa API al generatore di PiP per indicare l'area dell'attività visibile dopo la transizione in PiP.

  1. Aggiungi setSourceRectHint() a builder solo se lo stato definisce che l'app deve entrare in modalità PiP. In questo modo si evita di calcolare sourceRect quando l'app non deve entrare in PiP.
  2. Per impostare il valore sourceRect, utilizza i valori layoutCoordinates forniti dalla funzione onGloballyPositioned sul modificatore.
  3. Chiama setSourceRectHint() su builder e passa la variabile 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)