Elementos específicos à plataforma

Baixar exemplo Baixar o exemplo

As especificações da plataforma permitem que você consuma funcionalidades que só estão disponíveis em uma plataforma específica, sem implementar renderizadores ou efeitos personalizados.

O processo para consumir uma plataforma específica por meio de XAML ou por meio da API de código fluente é o seguinte:

  1. Adicione uma xmlns declaração ou using diretiva para o Xamarin.Forms.PlatformConfiguration namespace.
  2. Adicione uma xmlns declaração ou using diretiva para o namespace que contém a funcionalidade específica da plataforma:
    1. No iOS, esse é o Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace.
    2. No Android, esse é o Xamarin.Forms.PlatformConfiguration.AndroidSpecific namespace. Para o Android AppCompat, esse é o Xamarin.Forms.PlatformConfiguration.AndroidSpecific.AppCompat namespace.
    3. No Plataforma Universal do Windows, esse é o Xamarin.Forms.PlatformConfiguration.WindowsSpecific namespace.
  3. Aplique a plataforma específica do XAML ou do código com a On<T> API fluente. O valor de T pode ser os iOStipos , Androidou Windows do Xamarin.Forms.PlatformConfiguration namespace.

Observação

Observe que a tentativa de consumir uma plataforma específica em uma plataforma em que ela não está disponível não resultará em um erro. Em vez disso, o código será executado sem que a plataforma específica seja aplicada.

Específicos da plataforma consumidos por meio dos objetos de retorno IPlatformElementConfiguration da On<T> API de código fluente. Isso permite que várias específicas da plataforma sejam invocadas no mesmo objeto com o método em cascata.

Para obter mais informações sobre as especificações da plataforma fornecidas pelo Xamarin.Forms, consulte iOS Platform-Specifics, Android Platform-Specifics e Windows Platform-Specifics.

Criando específicos da plataforma

Os fornecedores podem criar suas próprias especificações de plataforma com Efeitos. Um Efeito fornece a funcionalidade específica, que é exposta por meio de uma plataforma específica. O resultado é um Efeito que pode ser consumido mais facilmente por meio de XAML e por meio de uma API de código fluente.

O processo para criar uma plataforma específica é o seguinte:

  1. Implemente a funcionalidade específica como um Efeito. Para obter mais informações, consulte Criando um efeito.
  2. Crie uma classe específica da plataforma que exporá o Efeito. Para obter mais informações, consulte Criando uma classe Platform-Specific.
  3. Na classe específica da plataforma, implemente uma propriedade anexada para permitir que a plataforma específica seja consumida por meio de XAML. Para obter mais informações, consulte Adicionando uma propriedade anexada.
  4. Na classe específica da plataforma, implemente métodos de extensão para permitir que o específico da plataforma seja consumido por meio de uma API de código fluente. Para obter mais informações, consulte Adicionando métodos de extensão.
  5. Modifique a implementação efeito para que o Efeito só seja aplicado se o específico da plataforma tiver sido invocado na mesma plataforma que o Efeito. Para obter mais informações, consulte Criando o efeito .

O resultado da exposição de um Efeito como específico da plataforma é que o Efeito pode ser consumido com mais facilidade por meio de XAML e por meio de uma API de código fluente.

Observação

É previsto que os fornecedores usem essa técnica para criar suas próprias especificações de plataforma, para facilitar o consumo dos usuários. Embora os usuários possam optar por criar suas próprias especificações de plataforma, deve-se observar que ele requer mais código do que criar e consumir um Efeito.

O aplicativo de exemplo demonstra uma Shadow plataforma específica que adiciona uma sombra ao texto exibido por um Label controle:

Shadow Platform-Specific

O aplicativo de exemplo implementa a Shadow plataforma específica em cada plataforma, para facilitar a compreensão. No entanto, além de cada implementação de Efeito específica da plataforma, a implementação da classe Shadow é praticamente idêntica para cada plataforma. Portanto, este guia se concentra na implementação da classe Shadow e no Efeito associado em uma única plataforma.

Para obter mais informações sobre Efeitos, consulte Personalizando controles com efeitos.

Criando uma classe específica da plataforma

Uma plataforma específica é criada como uma public static classe:

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

As seções a seguir discutem a implementação do Shadow Efeito específico e associado da plataforma.

Adicionando uma propriedade anexada

Uma propriedade anexada deve ser adicionada à plataforma específica para permitir o Shadow consumo por meio 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);
            }
        }
    }
}

A IsShadowed propriedade anexada é usada para adicionar o MyCompany.LabelShadowEffect Efeito a e removê-lo do controle ao qual a Shadow classe está anexada. Essa propriedade anexada registra o método OnIsShadowedPropertyChanged que será executado quando o valor da propriedade for alterado. Por sua vez, esse método chama o AttachEffect método ou DetachEffect para adicionar ou remover o efeito com base no valor da IsShadowed propriedade anexada. O Efeito é adicionado ou removido do controle modificando a coleção do Effects controle.

Observação

Observe que o Efeito é resolvido especificando um valor que é uma concatenação do nome do grupo de resolução e do identificador exclusivo especificado na implementação do Efeito. Para obter mais informações, consulte Criando um efeito.

Para obter mais informações sobre as propriedades anexadas, confira Propriedades anexadas.

Adicionando métodos de extensão

Os métodos de extensão devem ser adicionados à plataforma específica para permitir o Shadow consumo por meio de uma API de código fluente:

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;
        }
        ...
    }
}

Os IsShadowed métodos de extensão e SetIsShadowed invocam os acessadores get e set para a IsShadowed propriedade anexada, respectivamente. Cada método de extensão opera no IPlatformElementConfiguration<iOS, FormsElement> tipo , que especifica que o específico da plataforma pode ser invocado em Label instâncias do iOS.

Criando o efeito

O Shadow específico da plataforma adiciona o MyCompany.LabelShadowEffect a um Labele o remove. O exemplo de código a seguir mostra a implementação de LabelShadowEffect para o projeto do 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);
            }
        }
    }
}

O UpdateShadow método define Control.Layer propriedades para criar a sombra, desde que a IsShadowed propriedade anexada seja definida truecomo e desde que a Shadow plataforma específica tenha sido invocada na mesma plataforma para a qual o Efeito é implementado. Esse marcar é executado com o OnThisPlatform método .

Se o valor da Shadow.IsShadowed propriedade anexada for alterado em runtime, o Efeito precisará responder removendo a sombra. Portanto, uma versão substituída do OnElementPropertyChanged método é usada para responder à alteração da propriedade associável chamando o UpdateShadow método .

Para obter mais informações sobre como criar um efeito, consulte Criando um efeito e passando parâmetros de efeito como propriedades anexadas.

Consumindo a plataforma específica

O Shadow específico da plataforma é consumido em XAML definindo a Shadow.IsShadowed propriedade anexada como um boolean valor:

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

Como alternativa, ele pode ser consumido do C# usando a API fluente:

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

...

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