Compartilhar via


Elementos específicos à plataforma

Os itens específicos 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 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 Android AppCompat, este é o Xamarin.Forms.PlatformConfiguration.AndroidSpecific.AppCompat namespace.
    3. Na Plataforma Universal do Windows, esse é o Xamarin.Forms.PlatformConfiguration.WindowsSpecific namespace.
  3. Aplique o específico da plataforma a partir de XAML ou do código com a On<T> API fluente. O valor de T pode ser o iOS, Androidou Windows tipos do Xamarin.Forms.PlatformConfiguration namespace.

Observação

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

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

Para obter mais informações sobre as especificidades de plataforma fornecidas pelo Xamarin.Forms, consulte Especificações da plataforma iOS, Específicas da plataforma Android e Específicas da plataforma Windows.

Criando especificidades da plataforma

Os fornecedores podem criar suas próprias especificações de plataforma com o Effects. Um Efeito fornece a funcionalidade específica, que é exposta por meio de uma plataforma específica. O resultado é um Effect 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 irá expor o efeito. Para obter mais informações, consulte Criando uma classe específica da plataforma.
  3. Na classe específica da plataforma, implemente uma propriedade anexada para permitir que a específica da plataforma 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 a plataforma específica seja consumida 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 do 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 Effect como específico da plataforma é que o Effect pode ser consumido mais facilmente por meio de XAML e por meio de uma API de código fluente.

Observação

Prevê-se que os fornecedores usem essa técnica para criar suas próprias plataformas específicas, para facilitar o consumo pelos usuários. Embora os usuários possam optar por criar suas próprias especificações de plataforma, deve-se notar que isso requer mais código do que criar e consumir um Effect.

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

Plataforma de sombra específica

O aplicativo de exemplo implementa a Shadow plataforma específica em cada plataforma, para facilitar o entendimento. No entanto, além de cada implementação de Effect 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 Effect 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 Effect associado e específico da Shadow 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 Effect 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 ou DetachEffect método para adicionar ou remover o efeito com base no valor da IsShadowed propriedade anexada. O Effect é 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 e SetIsShadowed extension 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 Label, e 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 propriedade anexada IsShadowed esteja definida como true, e desde que o Shadow específico da plataforma tenha sido invocado na mesma plataforma para a qual o Effect é implementado. Essa verificação é realizada com o OnThisPlatform método.

Se o valor da propriedade anexada Shadow.IsShadowed for alterado em tempo de execução, o Efeito precisará responder removendo a sombra. Portanto, uma versão substituída do método é usada para responder à alteração de OnElementPropertyChanged propriedade vinculá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 o específico da plataforma

O Shadow específico da plataforma é consumido em XAML definindo a propriedade anexada Shadow.IsShadowed 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);