Características específicas de las plataformas

Ejemplo de descarga Descarga del ejemplo

Las características específicas de la plataforma permiten consumir funcionalidades que solo están disponibles en una plataforma específica, sin implementar representadores o efectos personalizados.

El proceso para consumir una plataforma específica a través de XAML o a través de la API de código fluida es el siguiente:

  1. Agregue una declaración xmlns o directiva para el espacio de nombres usingXamarin.Forms.PlatformConfiguration .
  2. Agregue una xmlns declaración o directiva para el espacio de nombres que contiene la funcionalidad específica de la using plataforma:
    1. En iOS, este es el espacio de Xamarin.Forms.PlatformConfiguration.iOSSpecific nombres .
    2. En Android, este es el espacio de Xamarin.Forms.PlatformConfiguration.AndroidSpecific nombres . Para Android AppCompat, este es el espacio de Xamarin.Forms.PlatformConfiguration.AndroidSpecific.AppCompat nombres .
    3. En la plataforma Windows universal, este es el espacio de Xamarin.Forms.PlatformConfiguration.WindowsSpecific nombres .
  3. Aplique el elemento específico de la plataforma desde XAML o desde el código con On<T> la API fluida. El valor de T puede ser los tipos , o del espacio de nombres iOSAndroidWindowsXamarin.Forms.PlatformConfiguration .

Nota:

Tenga en cuenta que si intenta consumir una plataforma específica en una plataforma en la que no está disponible, no se producirá un error. En su lugar, el código se ejecutará sin que se aplique el específico de la plataforma.

Los objetos devueltos por la API de código fluido se On<T> consumen específicamente de IPlatformElementConfiguration la plataforma. Esto permite invocar varias características específicas de la plataforma en el mismo objeto con el método en cascada.

Para obtener más información sobre los detalles específicos de la plataforma proporcionados por , vea Xamarin.FormsXamarin.Forms, Android Platform-Specificsy Windows Platform-Specifics.

Creación de características específicas de la plataforma

Los proveedores pueden crear sus propias características específicas de la plataforma con Efectos. Un efecto proporciona la funcionalidad específica, que luego se expone a través de una plataforma específica. El resultado es un efecto que se puede consumir más fácilmente a través de XAML y a través de una API de código fluida.

El proceso para crear una plataforma específica es el siguiente:

  1. Implemente la funcionalidad específica como un efecto. Para obtener más información, vea Crear un efecto.
  2. Cree una clase específica de la plataforma que exponga el efecto. Para obtener más información, vea Creating a Platform-Specific Class.
  3. En la clase específica de la plataforma, implemente una propiedad adjunta para permitir que la plataforma específica se consuma a través de XAML. Para obtener más información, vea Agregar una propiedad adjunta.
  4. En la clase específica de la plataforma, implemente métodos de extensión para permitir que la plataforma específica se consuma a través de una API de código fluida. Para obtener más información, vea Adding Extension Methods.
  5. Modifique la implementación del efecto para que el efecto solo se aplique si el específico de la plataforma se ha invocado en la misma plataforma que el efecto. Para obtener más información, vea Crear el efecto.

El resultado de exponer un efecto como específico de la plataforma es que el efecto se puede consumir más fácilmente a través de XAML y a través de una API de código fluida.

Nota:

Se prevé que los proveedores usen esta técnica para crear sus propias características específicas de la plataforma, para facilitar el consumo por parte de los usuarios. Aunque los usuarios pueden optar por crear sus propias características específicas de la plataforma, debe tenerse en cuenta que requiere más código que crear y consumir un efecto.

La aplicación de ejemplo muestra una aplicación específica de la plataforma que agrega una sombra al texto mostrado por un control Label :

Shadow Platform-Specific

La aplicación de ejemplo implementa la plataforma específica en cada plataforma, para facilitar la comprensión. Sin embargo, aparte de cada implementación de Efecto específica de la plataforma, la implementación de la clase Shadow es prácticamente idéntica para cada plataforma. Por lo tanto, esta guía se centra en la implementación de la clase Shadow y el efecto asociado en una sola plataforma.

Para obtener más información sobre los efectos, vea Personalización de controles con efectos.

Creación de una clase específica de la plataforma

Un específico de la plataforma se crea como una public static clase:

namespace MyCompany.Forms.PlatformConfiguration.iOS
{
  public static Shadow
  {
    ...
  }
}

En las secciones siguientes se describe la implementación del efecto específico Shadow de la plataforma y asociado.

Adición de una propiedad adjunta

Se debe agregar una propiedad adjunta a la plataforma específica para permitir Shadow el consumo a través de XAML:

namespace MyCompany.Forms.PlatformConfiguration.iOS
{
    using System.Linq;
    using Xamarin.Forms;
    using Xamarin.Forms.PlatformConfiguration;
    using FormsElement = Xamarin.Forms.Label;

    public static class Shadow
    {
        const string EffectName = "MyCompany.LabelShadowEffect";

        public static readonly BindableProperty IsShadowedProperty =
            BindableProperty.CreateAttached("IsShadowed",
                                            typeof(bool),
                                            typeof(Shadow),
                                            false,
                                            propertyChanged: OnIsShadowedPropertyChanged);

        public static bool GetIsShadowed(BindableObject element)
        {
            return (bool)element.GetValue(IsShadowedProperty);
        }

        public static void SetIsShadowed(BindableObject element, bool value)
        {
            element.SetValue(IsShadowedProperty, value);
        }

        ...

        static void OnIsShadowedPropertyChanged(BindableObject element, object oldValue, object newValue)
        {
            if ((bool)newValue)
            {
                AttachEffect(element as FormsElement);
            }
            else
            {
                DetachEffect(element as FormsElement);
            }
        }

        static void AttachEffect(FormsElement element)
        {
            IElementController controller = element;
            if (controller == null || controller.EffectIsAttached(EffectName))
            {
                return;
            }
            element.Effects.Add(Effect.Resolve(EffectName));
        }

        static void DetachEffect(FormsElement element)
        {
            IElementController controller = element;
            if (controller == null || !controller.EffectIsAttached(EffectName))
            {
                return;
            }

            var toRemove = element.Effects.FirstOrDefault(e => e.ResolveId == Effect.Resolve(EffectName).ResolveId);
            if (toRemove != null)
            {
                element.Effects.Remove(toRemove);
            }
        }
    }
}

La propiedad adjunta se usa para agregar el efecto al control al que está adjuntada la clase y IsShadowedMyCompany.LabelShadowEffectShadow quitarlo de él. Esta propiedad asociada registra el método OnIsShadowedPropertyChanged que se ejecutará cuando cambie el valor de la propiedad. A su vez, este método llama al método o para agregar o quitar AttachEffect el efecto en función del valor de la propiedad DetachEffectIsShadowed adjunta. El efecto se agrega o se quita del control modificando la colección Xamarin_Forms _Element_Effects" data-linktype="absolute-path">Effects del control.

Nota:

Tenga en cuenta que el efecto se resuelve especificando un valor que es una concatenación del nombre del grupo de resolución y el identificador único que se especifica en la implementación del efecto. Para obtener más información, vea Crear un efecto.

Para más información sobre las propiedades adjuntas, consulte Propiedades asociadas.

Agregar métodos de extensión

Los métodos de extensión deben agregarse a la plataforma específica para permitir Shadow el consumo a través de una API de código fluida:

namespace MyCompany.Forms.PlatformConfiguration.iOS
{
    using System.Linq;
    using Xamarin.Forms;
    using Xamarin.Forms.PlatformConfiguration;
    using FormsElement = Xamarin.Forms.Label;

    public static class Shadow
    {
        ...
        public static bool IsShadowed(this IPlatformElementConfiguration<iOS, FormsElement> config)
        {
            return GetIsShadowed(config.Element);
        }

        public static IPlatformElementConfiguration<iOS, FormsElement> SetIsShadowed(this IPlatformElementConfiguration<iOS, FormsElement> config, bool value)
        {
            SetIsShadowed(config.Element, value);
            return config;
        }
        ...
    }
}

Los IsShadowedSetIsShadowed métodos de extensión y invocan los accessors get y set para la IsShadowed propiedad adjunta, respectivamente. Cada método de extensión funciona en el tipo , que especifica que el específico de la plataforma se puede invocar en IPlatformElementConfiguration<iOS, FormsElement>Label instancias de iOS.

Creación del efecto

El Shadow específico de la plataforma agrega a y lo MyCompany.LabelShadowEffectLabel quita. En el ejemplo de código siguiente se muestra la implementación LabelShadowEffect para el proyecto de iOS:

[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(LabelShadowEffect), "LabelShadowEffect")]
namespace ShadowPlatformSpecific.iOS
{
    public class LabelShadowEffect : PlatformEffect
    {
        protected override void OnAttached()
        {
            UpdateShadow();
        }

        protected override void OnDetached()
        {
        }

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

            if (args.PropertyName == Shadow.IsShadowedProperty.PropertyName)
            {
                UpdateShadow();
            }
        }

        void UpdateShadow()
        {
            try
            {
                if (((Label)Element).OnThisPlatform().IsShadowed())
                {
                    Control.Layer.CornerRadius = 5;
                    Control.Layer.ShadowColor = UIColor.Black.CGColor;
                    Control.Layer.ShadowOffset = new CGSize(5, 5);
                    Control.Layer.ShadowOpacity = 1.0f;
                }
                else if (!((Label)Element).OnThisPlatform().IsShadowed())
                {
                    Control.Layer.ShadowOpacity = 0;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
            }
        }
    }
}

El método establece las propiedades para crear la sombra, siempre que la propiedad adjunta esté establecida en y siempre que se haya invocado el específico de la plataforma en la misma plataforma para la que se implementa UpdateShadowControl.Layer el IsShadowedtrueShadow efecto. Esta comprobación se realiza con el OnThisPlatform método .

Si el valor de propiedad adjunta cambia en tiempo de Shadow.IsShadowed ejecución, el efecto debe responder quitando la sombra. Por lo tanto, se usa una versión invalidada del método para responder al cambio de OnElementPropertyChanged propiedad enlazable mediante una llamada al UpdateShadow método .

Para obtener más información sobre cómo crear un efecto, vea Crear un efecto y Pasar parámetros de efecto como propiedades adjuntas.

Consumo específico de la plataforma

El Shadow elemento específico de la plataforma se consume en XAML estableciendo la Shadow.IsShadowed propiedad adjunta en un boolean valor:

<ContentPage xmlns:ios="clr-namespace:MyCompany.Forms.PlatformConfiguration.iOS" ...>
  ...
  <Label Text="Label Shadow Effect" ios:Shadow.IsShadowed="true" ... />
  ...
</ContentPage>

Como alternativa, se puede consumir desde C# mediante la API fluida:

using Xamarin.Forms.PlatformConfiguration;
using MyCompany.Forms.PlatformConfiguration.iOS;

...

shadowLabel.On<iOS>().SetIsShadowed(true);