Xamarin Forms -  Usando o recurso Effects


Neste artigo veremos como usar o Effects, uma alternativa a utilização dos Custom Renderers, para aplicar efeitos personlizados em controles Xamarin Forms.

O Xamarin Forms possui muitos controles, como Label, Entry, Button, ListView, etc. Cada um tem sua própria aparência e comportamento baseado na plataforma na qual você está rodando.

Mas o que acontece se você quiser personalizar a aparência de um controle ?

Vamos supor que você deseja adicionar uma cor à borda do controle Entry. Como esse controle não possui uma propriedade para definir a cor da borda, você vai precisar usar um custom render para conseguir fazer isso.

Nota: Para saber mais sobre Custom Renders veja o meu artigo:  Xamarin Forms - Usando Custom Renders

Agora, além dos Custom Renders temos disponível o recurso Effects no Xamarin Forms.

O recurso Effects ou Efeitos permite que os controles nativos em cada plataforma sejam personalizados e são geralmente usados para pequenas alterações de estilo.

A vantagem que Effects possui sobre os Custom Renderers é que eles são reutilizáveis e podem ser parametrizados para aumentar ainda mais a reutilização.(Os Custom Renderes são mais flexíveis e oferecem mais personalização)

Para usar o recurso Effects teremos que criar certas classes e adicionar comportamento a elas.

Cada classe PlatformEffect expõe as propriedades a seguir:

Cada classe PlatformEffect também expõe dois métodos a seguir, que devem ser substituídos para implementar um efeito:

Segundo a documentação, o processo para criar um efeito em cada projeto específico da plataforma é o seguinte:

  1. Crie uma subclasse da classe PlatformEffect.
  2. Substitua o método OnAttached e escreva a lógica para personalizar o controle.
  3. Substitua o método OnDetached e escreva a lógica para limpar a personalização do controle se necessário.
  4. Adicione um atributo ResolutionGroupName à classe do efeito. Esse atributo define um namespace para os efeitos que abrange toda a empresa, evitando conflitos com outros efeitos de mesmo nome. Observe que esse atributo só pode ser aplicado uma vez por projeto.
  5. Adicione um atributo ExportEffect à classe do efeito. Este atributo registra o efeito com uma ID exclusiva que é usada pelo Xamarin.Forms, em conjunto com o nome do grupo, para localizar o efeito antes de aplicá-lo a um controle. O atributo utiliza dois parâmetros – o nome do tipo de efeito e uma cadeia de caracteres exclusiva que será usada para localizar o efeito antes de aplicá-lo a um controle.

Neste artigo, como exemplo, vamos aplicar o efeito de de alterar a cor de fundo de um controle Entry ao receber o foco para amarelo.

Recursos usados:

Criando um projeto Xamarin Forms no VS 2017

Abra o  VS 2017 Community e clique em New Project e a seguir escolha Cross Platform -> Mobile App (Xamarin.Forms) e informe o nome XF_Effects:

A seguir selecione a Plataforma, eu marquei somente Android, e escolha a estratégia de compartilhamento que será .NET Standard.

Clique no botão OK. Nosso projeto já esta criado.

Criando o efeito personalizado para a view Entry

Vou implementar o efeito de alterar a cor de fundo da view Entry ao receber o foco para amarelo.

Vou fazer a implementação apenas para Android pois não tenho um ambiente para testar o iOS.

Vamo iniciar criando no projeto Android a classe chamada EfeitoCorDeFundo que herda da classe PlatfformEffect com o código abaixo:

using System;
using System.ComponentModel;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using XF_Effects.Droid;
[assembly: ResolutionGroupName("MacCompany")]
[assembly: ExportEffect(typeof(EfeitoCorDeFundo), nameof(EfeitoCorDeFundo))]
namespace XF_Effects.Droid
{
    public class EfeitoCorDeFundo :  PlatformEffect
    {
        Android.Graphics.Color backgroundColor;
        protected override void OnAttached()
        {
            try
            {
                backgroundColor = Android.Graphics.Color.White;
                Control.SetBackgroundColor(backgroundColor);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Não foi possível atribuir a propriedade ao controle anexado: ", ex.Message);
            }
        }
        protected override void OnDetached()
        {
            //nada
        }
        protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
        {
            base.OnElementPropertyChanged(args);
            try
            {
                if (args.PropertyName == "IsFocused")
                {
                    if (((Android.Graphics.Drawables.ColorDrawable)Control.Background).Color == backgroundColor)
                    {
                        Control.SetBackgroundColor(Android.Graphics.Color.Yellow);
                    }
                    else
                    {
                        Control.SetBackgroundColor(backgroundColor);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Não foi possível atribuir a propriedade ao controle anexado. Erro:", ex.Message);
            }
        }
    }
}

O atributo ResolutionGroupName cria um namespace para o nosso efeito, evitando problemas de duplicidade com efeitos de mesmo nome.

O atributo ExportEffect vai criar um id para nosso efeito que será utilizado pelo Xamarin.Forms.

O método OnAttached chama o método SetBackgroundColor para definir a cor da tela de fundo do controle como branco e também armazena essa cor em um campo. Essa funcionalidade é encapsulada em um bloco try/catch caso o controle a que o efeito está anexado não tenha uma propriedade de SetBackgroundColor. Nenhuma implementação é fornecida pelo método OnDetached porque nenhuma limpeza é necessária.

A substituição do evento OnElementPropertyChanged responde às alterações de propriedade associáveis no controle do Xamarin.Forms. Quando a propriedade IsFocused for alterada, a cor da tela de fundo do controle será alterada para amarelo se o controle estiver em foco, caso contrário, é alterada para branco.

Essa funcionalidade é encapsulada em um bloco try/catch caso o controle a que o efeito está anexado não tenha uma propriedade de BackgroundColor.

Agora vamos criar no projeto compartilhado uma pasta chamada Efeitos e nesta pasta vamos criar a classe EfeitoCorDeFundo :

using Xamarin.Forms;
namespace XF_Effects.Efeitos
{
    public class EfeitoCorDeFundo : RoutingEffect
    {
        public EfeitoCorDeFundo() : base ($"MacCompany.{nameof(EfeitoCorDeFundo)}")
        {}
    }
}

Esta classe herda da classe RoutingEffect que representa um efeito independente de plataforma que encapsula um efeito interno, que é geralmente é específico da plataforma.

A classe chama o construtor da classe base, passando um parâmetro composto por uma concatenação do nome do grupo de resolução (especificado usando o atributo ResolutionGroupName na classe do efeito) e pela ID exclusivo que foi especificada usando o atributo ExportEffect na classe do efeito.

Portanto, quando o Entry for inicializado em tempo de execução, uma nova instância de MacCompany.EfeitoCorDeFundo será adicionada à coleção Effects do controle.

Agora é só alegria ...

Consumindo o Efeito : EfeitoCorDeFundo

Vamos abrir o arquivo MainPage.xaml e definir o código a seguir:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XF_Effects.Efeitos"
             x:Class="XF_Effects.MainPage">
    <StackLayout>
        <Label Text="Usando Effects - Alterando a cor de fundo"   HorizontalOptions="Center" 
   VerticalOptions="CenterAndExpand" />
        <Entry Placeholder="Informe o nome" >
            <Entry.Effects>
                <local:EfeitoCorDeFundo/>
            </Entry.Effects>
        </Entry>
        <Entry Placeholder="Informe o emaill" >
            <Entry.Effects>
                <local:EfeitoCorDeFundo/>
            </Entry.Effects>
        </Entry>
        <Button Text="Enviar" />
    </StackLayout>
</ContentPage>

No código acima anexamos EfeitoCorDeFundo à instância de Entry adicionando o efeito à coleção Effects do controle.

         <Entry Placeholder="Informe o nome" >
            <Entry.Effects>
                <local:EfeitoCorDeFundo/>
            </Entry.Effects>
        </Entry>

Note que precisamos definir o namespace  xmlns:local="clr-namespace:XF_Effects.Efeitos".

Agora executando o projeto iremos obter o seguinte resultado:

Conforme esperado obtemos o controle Entry com cor de fundo amarela, ao receber o foco, definida como um efeito para ao Android.

Pegue o código do projeto aqui:  XF_Effects.zip (sem as referências)

E a paz de Deus, que excede todo o entendimento, guardará os vossos corações e os vossos pensamentos em Cristo Jesus. Filipenses 4:7

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Referências:


José Carlos Macoratti