Partager via


Création d’un effet

Les effets simplifient la personnalisation d’un contrôle. Cet article montre comment créer un effet qui change la couleur d’arrière-plan du contrôle Entry quand le contrôle obtient le focus.

Le processus de création d’un effet dans chaque projet spécifique à une plateforme est le suivant :

  1. Créez une sous-classe de la classe PlatformEffect.
  2. Remplacez la méthode OnAttached et écrivez une logique pour personnaliser le contrôle.
  3. Remplacez la méthode OnDetached et écrivez si nécessaire une logique pour nettoyer la personnalisation du contrôle.
  4. Ajoutez un attribut ResolutionGroupName à la classe de l’effet. Cet attribut définit un espace de noms à l’échelle de l’entreprise pour les effets, empêchant des collisions avec d’autres effets du même nom. Notez que cet attribut peut être appliqué seulement une fois par projet.
  5. Ajoutez un attribut ExportEffect à la classe de l’effet. Cet attribut inscrit l’effet avec un ID unique utilisé par Xamarin.Forms, ainsi que le nom du groupe, pour localiser l’effet avant de l’appliquer à un contrôle. L’attribut prend deux paramètres : le nom de type de l’effet et une chaîne unique qui est utilisée pour localiser l’effet avant de l’appliquer à un contrôle.

L’effet peut ensuite être consommé en l’attachant au contrôle approprié.

Remarque

Fournir un effet dans chaque projet de plateforme est facultatif. Une tentative d’utiliser un effet quand il n’est pas inscrit retourne une valeur non null qui ne fait rien.

L’exemple d’application montre un FocusEffect qui change la couleur d’arrière-plan d’un contrôle quand il obtient le focus. Le diagramme suivant illustre les responsabilités de chaque projet dans l’exemple d’application ainsi que les relations qu’ils entretiennent les uns avec les autres :

Responsabilités des projets d’effet de focus

Un contrôle Entry sur la page HomePage est personnalisé par la classe FocusEffect dans chaque projet spécifique à une plateforme. Chaque classe FocusEffect dérive de la classe PlatformEffect pour chaque plateforme. Il en résulte un rendu du contrôle Entry avec une couleur d’arrière-plan spécifique à la plateforme, qui change quand le contrôle obtient le focus, comme le montrent les captures d’écran suivantes :

Effet focus sur chaque plateforme, contrôle axé surEffet focus sur chaque plateforme, contrôle non centré

Création de l’effet sur chaque plateforme

Les sections suivantes décrivent l’implémentation de la classe FocusEffect pour chaque plateforme.

Projet iOS

L’exemple de code suivant illustre l’implémentation de FocusEffect pour le projet iOS :

using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly:ResolutionGroupName ("MyCompany")]
[assembly:ExportEffect (typeof(EffectsDemo.iOS.FocusEffect), nameof(EffectsDemo.iOS.FocusEffect))]
namespace EffectsDemo.iOS
{
    public class FocusEffect : PlatformEffect
    {
        UIColor backgroundColor;

        protected override void OnAttached ()
        {
            try {
                Control.BackgroundColor = backgroundColor = UIColor.FromRGB (204, 153, 255);
            } catch (Exception ex) {
                Console.WriteLine ("Cannot set property on attached control. Error: ", ex.Message);
            }
        }

        protected override void OnDetached ()
        {
        }

        protected override void OnElementPropertyChanged (PropertyChangedEventArgs args)
        {
            base.OnElementPropertyChanged (args);

            try {
                if (args.PropertyName == "IsFocused") {
                    if (Control.BackgroundColor == backgroundColor) {
                        Control.BackgroundColor = UIColor.White;
                    } else {
                        Control.BackgroundColor = backgroundColor;
                    }
                }
            } catch (Exception ex) {
                Console.WriteLine ("Cannot set property on attached control. Error: ", ex.Message);
            }
        }
    }
}

La méthode OnAttached définit la propriété BackgroundColor sur la couleur « light purple » (violet clair) avec la méthode UIColor.FromRGB et stocke également cette couleur dans un champ. Cette fonctionnalité est wrappée dans un bloc try/catch, au cas où le contrôle auquel l’effet est attaché n’aurait pas de propriété BackgroundColor. Aucune implémentation n’est fournie par la méthode OnDetached, car aucun nettoyage n’est nécessaire.

Le OnElementPropertyChanged remplacement répond aux modifications de propriété pouvant être liées sur le Xamarin.Forms contrôle. Quand la propriété IsFocused change, la propriété BackgroundColor du contrôle est changée en « white » (blanc) si le contrôle a le focus, sinon il est changé en « light purple » (violet clair). Cette fonctionnalité est wrappée dans un bloc try/catch, au cas où le contrôle auquel l’effet est attaché n’aurait pas de propriété BackgroundColor.

Projet Android

L’exemple de code suivant illustre l’implémentation de FocusEffect pour le projet Android :

using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(EffectsDemo.Droid.FocusEffect), nameof(EffectsDemo.Droid.FocusEffect))]
namespace EffectsDemo.Droid
{
    public class FocusEffect : PlatformEffect
    {
        Android.Graphics.Color originalBackgroundColor = new Android.Graphics.Color(0, 0, 0, 0);
        Android.Graphics.Color backgroundColor;

        protected override void OnAttached()
        {
            try
            {
                backgroundColor = Android.Graphics.Color.LightGreen;
                Control.SetBackgroundColor(backgroundColor);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
            }
        }

        protected override void OnDetached()
        {
        }

        protected override void OnElementPropertyChanged(System.ComponentModel.PropertyChangedEventArgs args)
        {
            base.OnElementPropertyChanged(args);
            try
            {
                if (args.PropertyName == "IsFocused")
                {
                    if (((Android.Graphics.Drawables.ColorDrawable)Control.Background).Color == backgroundColor)
                    {
                        Control.SetBackgroundColor(originalBackgroundColor);
                    }
                    else
                    {
                        Control.SetBackgroundColor(backgroundColor);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
            }
        }
    }
}

La méthode OnAttached appelle la méthode SetBackgroundColor pour définir la couleur d’arrière-plan du contrôle en vert clair et stocke également cette couleur dans un champ. Cette fonctionnalité est wrappée dans un bloc try/catch, au cas où le contrôle auquel l’effet est attaché n’aurait pas de propriété SetBackgroundColor. Aucune implémentation n’est fournie par la méthode OnDetached, car aucun nettoyage n’est nécessaire.

Le OnElementPropertyChanged remplacement répond aux modifications de propriété pouvant être liées sur le Xamarin.Forms contrôle. Quand la propriété IsFocused change, la couleur d’arrière-plan du contrôle est changée en « white » (blanc) si le contrôle a le focus, sinon il est changé en « light green » (vert clair). Cette fonctionnalité est wrappée dans un bloc try/catch, au cas où le contrôle auquel l’effet est attaché n’aurait pas de propriété BackgroundColor.

Projets UWP (Plateforme Windows universelle)

L’exemple de code suivant montre l’implémentation de FocusEffect pour le projet de plateforme UWP :

using Xamarin.Forms;
using Xamarin.Forms.Platform.UWP;

[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(EffectsDemo.UWP.FocusEffect), nameof(EffectsDemo.UWP.FocusEffect))]
namespace EffectsDemo.UWP
{
    public class FocusEffect : PlatformEffect
    {
        protected override void OnAttached()
        {
            try
            {
                (Control as Windows.UI.Xaml.Controls.Control).Background = new SolidColorBrush(Colors.Cyan);
                (Control as FormsTextBox).BackgroundFocusBrush = new SolidColorBrush(Colors.White);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
            }
        }

        protected override void OnDetached()
        {
        }
    }
}

La méthode OnAttached définit la propriété Background du contrôle sur « cyan » et définit la propriété BackgroundFocusBrush sur « white » (blanc). Cette fonctionnalité est wrappée dans un bloc try/catch, au cas où le contrôle auquel l’effet est attaché n’aurait pas ces propriétés. Aucune implémentation n’est fournie par la méthode OnDetached, car aucun nettoyage n’est nécessaire.

Consommation de l’effet

Le processus de consommation d’un effet à partir d’une bibliothèque .NET Standard ou d’un Xamarin.Forms projet de bibliothèque partagée est le suivant :

  1. Déclarez un contrôle qui sera personnalisé par l’effet.
  2. Attachez l’effet au contrôle en l’ajoutant à la collection Effects du contrôle.

Remarque

Une instance de l’effet ne peut être attachée qu’à un seul contrôle. Par conséquent, un effet doit être résolu deux fois pour être utilisé sur deux contrôles.

Consommation de l’effet en XAML

L’exemple de code XAML suivant montre un contrôle Entry auquel FocusEffect est attaché :

<Entry Text="Effect attached to an Entry" ...>
    <Entry.Effects>
        <local:FocusEffect />
    </Entry.Effects>
    ...
</Entry>

La classe FocusEffect de la bibliothèque .NET Standard prend en charge la consommation d’effets en XAML et elle apparaît dans l’exemple de code suivant :

public class FocusEffect : RoutingEffect
{
    public FocusEffect () : base ($"MyCompany.{nameof(FocusEffect)}")
    {
    }
}

La classe FocusEffect crée une sous-classe de la classe RoutingEffect, qui représente un effet indépendant de la plateforme qui wrappe un effet interne généralement spécifique à une plateforme. La classe FocusEffect appelle le constructeur de classe de base, en passant un paramètre constitué d’une concaténation du nom du groupe de résolution (spécifié avec l’attribut ResolutionGroupName sur la classe d’effet), et l’ID unique qui a été spécifié avec l’attribut ExportEffect sur la classe d’effet. Par conséquent, quand Entry est initialisé à l’exécution, une nouvelle instance de MyCompany.FocusEffect est ajoutée à la collection Effects du contrôle.

Les effets peuvent également être attachés à des contrôles avec un comportement ou avec des propriétés attachées. Pour plus d’informations sur l’attachement d’un effet à un contrôle avec un comportement, consultez Comportement d’effet réutilisable. Pour plus d’informations sur l’attachement d’un effet à un contrôle avec des propriétés attachées, consultez Passage de paramètres à un effet.

Consommation de l’effet en C#

Le contrôle Entry équivalent en C# est présenté dans l’exemple de code suivant :

var entry = new Entry {
  Text = "Effect attached to an Entry",
  ...
};

FocusEffect est attaché à la l’instance de Entry en ajoutant l’effet à la collection Effects du contrôle, comme illustré dans l’exemple de code suivant :

public HomePageCS ()
{
  ...
  entry.Effects.Add (Effect.Resolve ($"MyCompany.{nameof(FocusEffect)}"));
  ...
}

Effect.Resolve retourne un Effect pour le nom spécifié, qui est une concaténation du nom du groupe de résolution (spécifié avec l’attribut ResolutionGroupName sur la classe d’effet), et l’ID unique qui a été spécifié avec l’attribut ExportEffect sur la classe d’effet. Si une plateforme ne fournit pas l’effet, la méthode Effect.Resolve retourne une valeur non null.

Résumé

Cet article montre comment créer un effet qui change la couleur d’arrière-plan du contrôle Entry quand le contrôle obtient le focus.