Creazione di un effetto

Gli effetti semplificano la personalizzazione di un controllo. Questo articolo spiega come creare un effetto che cambia il colore di sfondo del controllo Entry quando il controllo riceve lo stato attivo.

Il processo per la creazione di un effetto in ogni progetto specifico della piattaforma è come segue:

  1. Creare una sottoclasse della classe PlatformEffect.
  2. Eseguire l'override del metodo OnAttached scrivere la logica per personalizzare il controllo.
  3. Eseguire l'override del metodo OnDetached e scrivere la logica per pulire la personalizzazione del controllo, se necessario.
  4. Aggiungere un attributo ResolutionGroupName alla classe di effetto. Questo attributo imposta uno spazio dei nomi a livello di società per gli effetti, per evitare che si verifichino conflitti con altri effetti omonimi. Si noti che questo attributo può essere applicato solo una volta per ogni progetto.
  5. Aggiungere un attributo ExportEffect alla classe di effetto. Questo attributo registra l'effetto con un ID univoco usato da Xamarin.Forms, insieme al nome del gruppo, per individuare l'effetto prima di applicarlo a un controllo. L'attributo accetta due parametri: il nome del tipo di effetto e una stringa univoca che consente di individuare l'effetto prima di applicarlo a un controllo.

L'effetto può quindi essere utilizzato associandolo al controllo appropriato.

Nota

La specifica di un effetto nel progetto di ogni piattaforma è facoltativa. Se si tenta di usare un effetto quando non ne sono stati registrati, verrà restituito un valore non null che non esegue alcuna operazione.

L'applicazione di esempio illustra un FocusEffect che cambia il colore di sfondo di un controllo quando ottiene lo stato attivo. Il diagramma seguente illustra le responsabilità di ogni progetto nell'applicazione di esempio, insieme alle relazioni tra di essi:

Responsabilità dei progetti per l'effetto stato attivo

Un controllo Entry in HomePage è personalizzato dalla classe FocusEffect in ogni progetto specifico della piattaforma. Ogni classe FocusEffect deriva dalla classe PlatformEffect per ogni piattaforma. Di conseguenza il rendering di ogni controllo Entry viene eseguito con un colore di sfondo specifico della piattaforma, che cambia quando il controllo ottiene lo stato attivo, come illustrato negli screenshot seguenti:

Effetto messa a fuoco su ogni piattaforma, controllo con stato attivoEffetto messa a fuoco su ogni piattaforma, controllo non incentrato

Creazione dell'effetto in ogni piattaforma

Le sezioni seguenti illustrano l'implementazione specifica della piattaforma della classe FocusEffect.

Progetto iOS

L'esempio di codice seguente mostra l'implementazione di FocusEffect per il progetto 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);
            }
        }
    }
}

Il metodoOnAttached imposta la proprietà BackgroundColor del controllo su viola chiaro con il metodo UIColor.FromRGB e archivia questo colore in un campo. Questa funzionalità è incapsulata in un blocco try/catch, nell'evenienza in cui il controllo a cui l'effetto è associato non avesse una proprietà BackgroundColor. Il metodo OnDetached non fornisce alcuna implementazione perché non sono necessarie operazioni di pulizia.

L'override OnElementPropertyChanged risponde alle modifiche alle proprietà associabili nel Xamarin.Forms controllo . Quando la proprietà IsFocused cambia, la proprietà BackgroundColor del controllo imposta bianco, se il controllo ha lo stato attivo, oppure viola chiaro in caso contrario. Questa funzionalità è incapsulata in un blocco try/catch, nell'evenienza in cui il controllo a cui l'effetto è associato non avesse una proprietà BackgroundColor.

Progetto Android

L'esempio di codice seguente mostra l'implementazione di FocusEffect per il progetto 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);
            }
        }
    }
}

Il metodo OnAttached esegue una chiamata al metodo SetBackgroundColor per impostare il colore di sfondo del controllo su verde chiaro e archivia anche questo colore in un campo. Questa funzionalità è incapsulata in un blocco try/catch, nell'evenienza in cui il controllo a cui l'effetto è associato non avesse una proprietà SetBackgroundColor. Il metodo OnDetached non fornisce alcuna implementazione perché non sono necessarie operazioni di pulizia.

L'override OnElementPropertyChanged risponde alle modifiche alle proprietà associabili nel Xamarin.Forms controllo . Quando la proprietà IsFocused cambia, il colore di sfondo del controllo imposta bianco, se il controllo ha lo stato attivo, oppure verde chiaro in caso contrario. Questa funzionalità è incapsulata in un blocco try/catch, nell'evenienza in cui il controllo a cui l'effetto è associato non avesse una proprietà BackgroundColor.

Progetti della piattaforma UWP (Universal Windows Platform)

L'esempio di codice seguente mostra l'implementazione di FocusEffect per il progetto UWP (Universal Windows Platform):

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()
        {
        }
    }
}

Il metodo OnAttached imposta la proprietà Background del controllo su ciano e imposta la proprietà BackgroundFocusBrush su bianco. Questa funzionalità è incapsulata in un blocco try/catch, nell'evenienza in cui il controllo a cui l'effetto è associato non avesse queste proprietà. Il metodo OnDetached non fornisce alcuna implementazione perché non sono necessarie operazioni di pulizia.

Utilizzo dell'effetto

Il processo per l'utilizzo di un effetto da una libreria .NET Standard o da un Xamarin.Forms progetto di libreria condivisa è il seguente:

  1. Dichiarare un controllo che verrà personalizzato dall'effetto.
  2. Associare l'effetto al controllo aggiungendolo alla raccolta Effects del controllo.

Nota

Un'istanza dell'effetto può essere associata solo a un singolo controllo. Pertanto, per poter essere usato su due controlli, un effetto deve essere risolto due volte.

Utilizzo dell'effetto in XAML

L'esempio di codice XAML seguente mostra un controllo Entry a cui è associato FocusEffect:

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

La classe FocusEffect nella libreria .NET Standard supporta l'utilizzo dell'effetto in XAML, come viene illustrato nell'esempio di codice seguente:

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

La classe FocusEffect crea una sottoclasse della classe RoutingEffect, che rappresenta un effetto indipendente dalla piattaforma che esegue il wrapping di un effetto interno, in genere specifico della piattaforma. La classe FocusEffect chiama il costruttore della classe di base, passando un parametro costituito da una concatenazione del nome del gruppo di risoluzione, specificato usando l'attributo ResolutionGroupName della classe di effetto, e dell'ID univoco specificato usando l'attributo ExportEffect sulla classe di effetto. Pertanto, quando il controllo Entry viene inizializzato in fase di esecuzione, una nuova istanza di MyCompany.FocusEffect viene aggiunta alla raccolta Effects del controllo.

Gli effetti possono inoltre essere associati ai controlli per mezzo di un comportamento o utilizzando le proprietà associate. Per altre informazioni sull'associazione di un effetto a un controllo utilizzando un comportamento, vedere Reusable EffectBehavior (EffectBehavior riutilizzabile). Per altre informazioni sull'associazione di un effetto a un controllo usando le proprietà associate, vedere Passing Parameters to an Effect (Passare parametri a un effetto).

Utilizzo dell'effetto in C#

Il codice C# equivalente per Entry è visualizzato nell'esempio seguente:

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

FocusEffect viene associato all'istanza di Entry aggiungendo l'effetto alla raccolta Effects del controllo, come illustrato nell'esempio di codice seguente:

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

Effect.Resolve restituisce un valore Effect per il nome specificato, costituito da una concatenazione del nome del gruppo di risoluzione, specificato usando l'attributo ResolutionGroupName della classe di effetto, e dell'ID univoco specificato usando l'attributo ExportEffect sulla classe di effetto. Se una piattaforma non fornisce l'effetto, il metodo Effect.Resolve restituirà un valore non null.

Riepilogo

Questo articolo ha spiegato come creare un effetto che cambia il colore di sfondo del controllo Entry quando il controllo riceve lo stato attivo.