Partager via


Personnalisation d’un ContentPage

Un ContentPage est un élément visuel qui affiche une seule vue et occupe la majeure partie de l’écran. Cet article montre comment créer un renderer personnalisé pour la page ContentPage afin de permettre aux développeurs de remplacer le rendu natif par défaut par leur propre personnalisation spécifique à la plateforme.

Chaque Xamarin.Forms contrôle a un renderer associé pour chaque plateforme qui crée une instance d’un contrôle natif. Lorsqu’une ContentPage application est rendue Xamarin.Forms , dans iOS, la PageRenderer classe est instanciée, ce qui instancie à son tour un contrôle natif UIViewController . Sur la plateforme Android, la classe PageRenderer instancie un contrôle ViewGroup. Sur la plateforme Windows universelle (UWP), la classe PageRenderer instancie un contrôle FrameworkElement. Pour plus d’informations sur les classes de renderer et de contrôle natives qui contrôlent Xamarin.Forms la correspondance, consultez Les classes de base du renderer et les contrôles natifs.

Le diagramme suivant illustre la relation entre ContentPage et les contrôles natifs correspondants qui l’implémentent :

Relation entre la classe ContentPage et les contrôles natifs qui l’implémentent

Vous pouvez tirer profit du processus de rendu pour implémenter des personnalisations spécifiques à la plateforme en créant un renderer personnalisé pour un ContentPage sur chaque plateforme. Le processus pour y parvenir est le suivant :

  1. Créez une Xamarin.Forms page.
  2. Consommer la page à partir de Xamarin.Forms.
  3. Créez le renderer personnalisé pour la page sur chaque plateforme.

Nous allons à présent présenter chaque élément à tour de rôle pour implémenter un CameraPage qui fournit un flux vidéo en temps réel et qui permet de capturer une photo.

Création de la Xamarin.Forms page

Vous pouvez ajouter un élément non modifiable ContentPage au projet partagé Xamarin.Forms , comme illustré dans l’exemple de code XAML suivant :

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CustomRenderer.CameraPage">
    <ContentPage.Content>
    </ContentPage.Content>
</ContentPage>

De même, le fichier code-behind pour le ContentPage doit également rester inchangé, comme le montre l’exemple de code suivant :

public partial class CameraPage : ContentPage
{
    public CameraPage ()
    {
        // A custom renderer is used to display the camera UI
        InitializeComponent ();
    }
}

L’exemple de code suivant montre comment créer la page en C# :

public class CameraPageCS : ContentPage
{
    public CameraPageCS ()
    {
    }
}

Une instance de CameraPage est utilisée pour afficher le flux vidéo en temps réel sur chaque plateforme. La personnalisation du contrôle étant effectuée dans le renderer personnalisé, aucune implémentation supplémentaire n’est nécessaire dans la classe CameraPage.

Consommation de la Xamarin.Forms page

Le vide CameraPage doit être affiché par l’application Xamarin.Forms . Cela se produit quand un bouton est actionné dans l’instance MainPage, entraînant à son tour l’exécution de la méthode OnTakePhotoButtonClicked, comme le montre l’exemple de code suivant :

async void OnTakePhotoButtonClicked (object sender, EventArgs e)
{
    await Navigation.PushAsync (new CameraPage ());
}

Ce code accède simplement à CameraPage, sur lequel les renderers personnalisés personnalisent l’apparence de la page sur chaque plateforme.

Création du renderer de page sur chaque plateforme

Le processus de création de la classe de renderer personnalisé est le suivant :

  1. Créez une sous-classe de la classe PageRenderer.
  2. Remplacez la méthode OnElementChanged qui restitue la page native et écrivez la logique pour la personnaliser. La OnElementChanged méthode est appelée lorsque le contrôle correspondant Xamarin.Forms est créé.
  3. Ajoutez un ExportRenderer attribut à la classe renderer de page pour spécifier qu’il sera utilisé pour afficher la Xamarin.Forms page. Cet attribut est utilisé pour inscrire le renderer personnalisé avec Xamarin.Forms.

Remarque

Il est facultatif de fournir un renderer de page dans chaque projet de plateforme. Si un renderer de page n’est pas inscrit, le renderer par défaut de la page est utilisé.

Le diagramme suivant montre les responsabilités de chaque projet dans l’exemple d’application ainsi que la relation qu’ils entretiennent les uns avec les autres :

Responsabilités du projet de renderer personnalisé CameraPage

L’instance CameraPage est restituée par des classes CameraPageRenderer spécifiques à la plateforme qui dérivent toutes de la classe PageRenderer pour cette plateforme. Chaque instance CameraPage est alors restituée avec un flux vidéo en temps réel, comme le montrent les captures d’écran suivantes :

CameraPage sur chaque plateforme

La PageRenderer classe expose la OnElementChanged méthode, appelée lorsque la Xamarin.Forms page est créée pour afficher le contrôle natif correspondant. Cette méthode prend un paramètre ElementChangedEventArgs qui contient les propriétés OldElement et NewElement. Ces propriétés représentent l’élément Xamarin.Forms auquel le renderer a été attaché, et l’élément Xamarin.Forms auquel le renderer est attaché, respectivement. Dans l’exemple d’application, la propriété OldElement est null et la propriété NewElement contient une référence à l’instance CameraPage.

Une version substituée de la méthode OnElementChanged dans la classe CameraPageRenderer est l’emplacement où effectuer la personnalisation de la page native. Une référence à l’instance Xamarin.Forms de page en cours de rendu peut être obtenue via la Element propriété.

Chaque classe de renderer personnalisée est décorée avec un ExportRenderer attribut qui inscrit le renderer avec Xamarin.Forms. L’attribut prend deux paramètres : le nom de type de la Xamarin.Forms page en cours de rendu et le nom de type du renderer personnalisé. Le préfixe assembly de l’attribut spécifie que l’attribut s’applique à la totalité de l’assembly.

Les sections suivantes décrivent l’implémentation du renderer personnalisé CameraPageRenderer pour chaque plateforme.

Création du renderer de page sur iOS

L’exemple de code suivant illustre le renderer de page pour la plateforme iOS :

[assembly:ExportRenderer (typeof(CameraPage), typeof(CameraPageRenderer))]
namespace CustomRenderer.iOS
{
    public class CameraPageRenderer : PageRenderer
    {
        ...

        protected override void OnElementChanged (VisualElementChangedEventArgs e)
        {
            base.OnElementChanged (e);

            if (e.OldElement != null || Element == null) {
                return;
            }

            try {
                SetupUserInterface ();
                SetupEventHandlers ();
                SetupLiveCameraStream ();
                AuthorizeCameraUse ();
            } catch (Exception ex) {
                System.Diagnostics.Debug.WriteLine (@"            ERROR: ", ex.Message);
            }
        }
        ...
    }
}

L’appel à la méthode OnElementChanged de la classe de base instancie un contrôle UIViewController iOS. Le flux de caméra en direct est rendu uniquement à condition que le renderer ne soit pas déjà attaché à un élément existant Xamarin.Forms , et à condition qu’une instance de page existe qui soit rendue par le renderer personnalisé.

La page est ensuite personnalisée par une série de méthodes qui utilisent les API AVCapture pour fournir le flux en temps réel à partir de la caméra et la possibilité de capturer une photo.

Création du renderer de page sur Android

L’exemple de code suivant illustre le renderer de page pour la plateforme Android :

[assembly: ExportRenderer(typeof(CameraPage), typeof(CameraPageRenderer))]
namespace CustomRenderer.Droid
{
    public class CameraPageRenderer : PageRenderer, TextureView.ISurfaceTextureListener
    {
        ...
        public CameraPageRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null || Element == null)
            {
                return;
            }

            try
            {
                SetupUserInterface();
                SetupEventHandlers();
                AddView(view);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(@"            ERROR: ", ex.Message);
            }
        }
        ...
    }
}

L’appel à la méthode OnElementChanged de la classe de base instancie un contrôle ViewGroup Android, qui est en fait un groupe de vues. Le flux de caméra en direct est rendu uniquement à condition que le renderer ne soit pas déjà attaché à un élément existant Xamarin.Forms , et à condition qu’une instance de page existe qui soit rendue par le renderer personnalisé.

La page est ensuite personnalisée en appelant une série de méthodes qui utilisent l’API Camera pour fournir le flux en temps réel de la caméra et la possibilité de capturer une photo, puis la méthode AddView est appelée pour ajouter l’interface utilisateur du flux vidéo en temps réel à ViewGroup. Sur Android, notez qu’il est également nécessaire de remplacer la méthode OnLayout pour effectuer les opérations de mesure et de disposition sur la vue.

Création du renderer de page sur UWP

L’exemple de code suivant illustre le renderer de page pour UWP :

[assembly: ExportRenderer(typeof(CameraPage), typeof(CameraPageRenderer))]
namespace CustomRenderer.UWP
{
    public class CameraPageRenderer : PageRenderer
    {
        ...
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null || Element == null)
            {
                return;
            }

            try
            {
                ...
                SetupUserInterface();
                SetupBasedOnStateAsync();

                this.Children.Add(page);
            }
            ...
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            page.Arrange(new Windows.Foundation.Rect(0, 0, finalSize.Width, finalSize.Height));
            return finalSize;
        }
        ...
    }
}

L’appel à la méthode OnElementChanged de la classe de base instancie un contrôle FrameworkElement sur lequel la page est restituée. Le flux de caméra en direct est rendu uniquement à condition que le renderer ne soit pas déjà attaché à un élément existant Xamarin.Forms , et à condition qu’une instance de page existe qui soit rendue par le renderer personnalisé. La page est ensuite personnalisée en appelant une série de méthodes qui utilisent l’API MediaCapture pour fournir le flux en temps réel de la caméra et la possibilité de capturer une photo, puis la page personnalisée est ajoutée à la collection Children pour affichage.

Quand vous implémentez un renderer personnalisé qui dérive de PageRenderer sur UWP, la méthode ArrangeOverride doit également être implémentée pour organiser les contrôles de page car le renderer de base ne sait pas quoi en faire. Sinon, vous obtenez une page vierge. Ainsi, dans cet exemple, la méthode ArrangeOverride appelle la méthode Arrange sur l’instance Page.

Remarque

Il est important d’arrêter et de supprimer les objets qui fournissent un accès à la caméra dans une application UWP. Si vous ne le faites pas, il peut se produire une interférence avec d’autres applications qui tentent d’accéder à la caméra de l’appareil. Pour plus d’informations, consultez Afficher l’aperçu de la caméra.

Résumé

Dans cet article, nous avons vu comment créer un renderer personnalisé pour la page ContentPage afin de permettre aux développeurs de remplacer le rendu natif par défaut par leur propre personnalisation spécifique à la plateforme. Un ContentPage est un élément visuel qui affiche une seule vue et occupe la majeure partie de l’écran.