Aplicación de un efecto a un elemento de Xamarin.Forms

Completado

Los efectos son clases específicas de una plataforma que modifican el control nativo subyacente usado por un elemento de Xamarin.Forms. Los controles nativos suelen ser mucho más flexibles y eficaces que el elemento de Xamarin.Forms. Por ejemplo, el efecto Entry de Xamarin.Forms no expone una opción de sombra paralela de forma directa, sino que cada plataforma compatible tiene algún mecanismo para crearla. Puede acceder a esas opciones mediante efectos.

Diagram showing an Android ShadowEffect applied to an Entry control.

Funcionamiento de los efectos

Los efectos se aplican una vez que el representador ha creado el control nativo. El efecto, por tanto, solo tiene que proporcionar las modificaciones concretas de las que es responsable. En el diagrama siguiente, el efecto agrega el comportamiento de sombra paralela.

Diagram showing the separation of shared and platform code, with an iOS shadow effect being applied to a button.

Para cualquier efecto, necesita una clase por plataforma, ya que el efecto realiza trabajo específico de la plataforma. En el diagrama anterior, por ejemplo, IOSShadowEffect aplica API específicas de iOS. Como quiere admitir Android con el efecto de sombra paralela, también necesitará una clase de Android. Las clases específicas de la plataforma se derivan de la clase base PlatformEffect.

Las clases derivadas PlatformEffect se registran con un valor de cadena y el código de la aplicación de Xamarin.Forms puede buscarlas por esa cadena y agregarlas a un elemento.

Resolver y agregar un efecto a un elemento

Desde dentro del código de la aplicación compartida de Xamarin.Forms, puede buscar un efecto mediante Effect.Resolve. Ese método acepta un parámetro de cadena y hace coincidir esa cadena con un identificador PlatformEffect. El efecto devuelto se convierte en su tipo de antecesor, Effect, como se muestra aquí:

    // This code finds a PlatformEffect registered as "MyCompany.ShadowEffect"
    // on whatever platform we're currently running on.
    Effect shadowEffect = Effect.Resolve("MyCompany.ShadowEffect");

Los elementos de Xamarin.Forms tienen una propiedad Effects de tipo IList<Effect>. Puede aplicar el comportamiento de Effect si lo agrega a esa colección:

    interestingButton.Effects.Add(shadowEffect);

También puede quitar el comportamiento si quita Effect de la colección:

    interestingButton.Effects.Remove(shadowEffect);

No compartir instancias de efecto

Cada llamada a Resolve devuelve una nueva instancia de Effect. Esa instancia solo se debe usar con un objeto Element. Para aplicar una instancia de Effect a varios elementos, llame a Resolve una vez por cada elemento, como se muestra en el código siguiente:

    var shadowEffectForInteresting = Effect.Resolve("MyCompany.ShadowEffect");
    interestingButton.Effects.Add(shadowEffectForInteresting);

    var shadowEffectForOther = Effect.Resolve("MyCompany.ShadowEffect");
    otherButton.Effects.Add(shadowEffectForOther);

Usar un efecto desde XAML

Para aplicar un efecto desde XAML, tendrá que crear una clase derivada de RoutingEffect. El constructor de clase base llama a Resolve y solo tendrá que pasarle la cadena de identificador. Como se muestra en el código siguiente, no se necesita ninguna implementación adicional en la clase derivada:

public class ShadowEffect : RoutingEffect()
{
    public ShadowEffect() : base("MyCompany.ShadowEffect")
    {}
}

Esa clase ya se puede usar en XAML para crear instancias y agregar el comportamiento del efecto:

<Button ...>
    <Button.Effects>
        <local:ShadowEffect />
    </Button.Effects>
</Button>

El uso de RoutingEffects también puede hacer que los efectos que se aplican en el código sean más elegantes mediante el aislamiento de RoutingEffects repetidas codificadas de forma rígida en una única ubicación. Después, puede permitir que el código de la página use referencias fuertemente tipadas:

    // No need for an explicit call to Resolve with a 'magic string'
    interestingButton.Effects.Add(new ShadowEffect());