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 :
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 :
- Créez une Xamarin.Forms page.
- Consommer la page à partir de Xamarin.Forms.
- 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 :
- Créez une sous-classe de la classe
PageRenderer
. - Remplacez la méthode
OnElementChanged
qui restitue la page native et écrivez la logique pour la personnaliser. LaOnElementChanged
méthode est appelée lorsque le contrôle correspondant Xamarin.Forms est créé. - 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 :
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 :
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.