Loupe

Mettre en place le "Picture In Picture" (PIP) dans vos applications Xamarin.Android

Depuis la version 8.0 d'Android (et son niveau d'API 26), il est possible d'utiliser les APIs de multi-fenêtrages pour afficher plusieurs activités côte à côte sur le même écran. Au cours de cet article, nous verrons comment utiliser ces fonctionnalités et surtout la fonctionnalité "Picture In Picture", qui permet d'afficher une partie de votre activité de manière réduite. L'utilisateur continue ainsi à utiliser la fonctionnalité en cours tout en naviguant dans votre application.

Bien que le plus souvent utilisée pour les applications de type lecteur vidéo, il faut garder en tête que cette fonctionnalité est disponible à tout moment: Google Maps l'utilise par exemple pour vous permettre de continuer à voir votre itinéraire alors que vous êtes sur le menu principal de votre téléphone :)

Google Maps.jpg

La première étape pour pouvoir utiliser le Picture In Picture est d'ajouter les propriétés ResizeableActivity et SupportsPictureInPicture à votre activité. Vous pouvez également rajouter ConfigurationChanges pour indiquer quand le système Android doit recharger votre activité (afin de ne pas perdre le contexte) :

[Activity(Label = "@string/app_name", 
        Theme = "@style/AppTheme.NoActionBar",
        ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.SmallestScreenSize | ConfigChanges.ScreenLayout | ConfigChanges.Orientation,
        ResizeableActivity = true,
        SupportsPictureInPicture = true,
        MainLauncher = true)]

Passer en mode PIP

A présent, vous avez pour ainsi dire terminé ! En effet, il ne vous reste plus qu'à appeler la méthode EnterPictureInPictureMode pour activer le mode PIP. Imaginez ainsi que vous disposiez d'un activité avec une VideoView (_videoView) et 2 boutons (un pour lancer la lecture et l'autre pour passer en mode PIP). Le code suivant vous permet alors de passer en mode Picture In Picture:

public void GoInPipMode()
{
    if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
    {
        var aspectRatio = new Rational(_videoView.Width, _videoView.Height);

        var pictureInPictureParamsBuilder = new PictureInPictureParams.Builder();
        pictureInPictureParamsBuilder.SetAspectRatio(aspectRatio);

        EnterPictureInPictureMode(pictureInPictureParamsBuilder.Build());
    }
    else
    {
        Toast.MakeText(this, "API 26 needed to perform PiP", ToastLength.Long).Show();
    }
}

Gérer les contrôles affichés

Le seul problème, c'est que toute votre activité passe en taille réduite ! Ainsi, les boutons restent présents mais masquent une bonne partie de la vue, pas forcément l'effet désiré...

Full.jpg   PIP.jpg

Qu'à cela ne tienne, Android met à notre disposition la méthode OnPictureInPictureModeChanged que nous pouvons surcharger pour jouer sur les éléments graphiques qui seront affichés / masqués :

public override void OnPictureInPictureModeChanged(bool isInPictureInPictureMode, Configuration newConfig)
{
    if(isInPictureInPictureMode)
    {
        _playButton.Visibility = ViewStates.Gone;
        _pipButton.Visibility = ViewStates.Gone;
    }
    else
    {
        _playButton.Visibility = ViewStates.Visible;
        _pipButton.Visibility = ViewStates.Visible;
    }
}

Good.jpg

Et le bouton Home dans tout ça ?

Si vous appuyez sur le bouton Home de votre téléphone, vous remarquerez que votre application ne passe pas en mode PIP. Pour cela, il faut déclencher cet appel lorsque l'application passe en arrière-plan, via la méthode OnUserLeaveHint:

protected override void OnUserLeaveHint()
{
    GoInPipMode();
}

Et le tour est joué ! Bien sûr, il y a plusieurs possibilités pour parvenir à ce résultat, le code présenté ci-dessous est plus un POC qu'autre chose. Mais cela vous donne un aperçu du résultat possible ! Gardez aussi en tête que vous avez la possibilité d'ajouter des boutons personnalisés sur la miniature qui apparait: par défaut, les boutons "Fermer" et "Plein écran" sont visibles mais vous pouvez rajouter les boutons que vous souhaitez, comme pour mettre la vidéo en pause, etc.

Ci-dessous, une petite vidéo du résultat :

Happy coding et bon PIP à tous :)

 

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus