Xamarin Forms - Apresentando o Visual State Manager (VSM)

 Neste artigo vou apresentar o Visual State Manager que foi introduzido na versão 3.0 do Xamarin Forms.

A versão 3.0 do Xamarin Forms trouxe alguns novos recursos como FlexLayout, StyleSheets, Visual State Manager, Right-To-Left-Localization, etc. Para saber mais detalhes das novidades visite o link : release notes

Hoje vou apresentar o recurso Visual State Manager.(VSM)

O Visual State Manager (VSM) fornece uma maneira estruturada de fazer alterações visuais na interface do usuário a partir do código XAML. Na maioria dos casos, a interface do usuário é definida em XAML e isso inclui marcação descrevendo como o VSM ou Gerenciador de Estado Visual afeta os elementos visuais da interface.  Usamos o VSM para fazer alterações nos elementos XAML com base nos estados visuais definidos a partir do código.

O VSM introduz o conceito de estados visuais. Uma view Xamarin.Forms como um Button pode ter várias aparências visuais diferentes, dependendo de seu estado que pode ser:  desativado, pressionado ou possuindo o foco de entrada. Estes são os estados do botão.

Os estados visuais são coletados em grupos de estados visuais. Todos os estados visuais dentro de um grupo são mutuamente exclusivos, e, tanto estados visuais quanto grupos de estados visuais são identificados por strings de texto simples.

O VSM do Xamarin.Forms define um grupo de estados visuais chamado "CommonStates" com três estados visuais:

Este grupo de estados visuais é suportado por todas as classes derivadas de VisualElement, que é a classe base para View e Page.

Você também pode definir seus próprios grupos de estados visuais e estados visuais, como iremos mostrar em outro artigo.

Os estados comuns

O VSM permite incluir seções no arquivo XAML que podem alterar a aparência visual de uma view se a view estiver no estado normal ou desativada ou se possuir o foco de entrada. Estes são conhecidos como estados comuns.

Por exemplo, suponha que você tenha uma view Entry em sua página e deseja que a aparência visual desta view seja alterada da seguinte forma:

1 - A view Entry deve ter um fundo azul claro com texto branco quando a estiver desativada;
2 - A view Entry deve ter um fundo de verde claro com texto preto no estado normal;
3 - A view Entry deve expandir para o dobro de sua altura normal quando tiver o foco de entrada;

Para implementar essas funcionalidades você pode anexar a marcação do VSM a uma view individual ou pode definí-la em um estilo se ela se aplicar a várias views.

A seguir veremos a utilização dessas duas abordagens.

  • Recursos Usados

    Criando o projeto 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_VSM1:

    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.

    Pronto nosso projeto já esta criado. ( Atualmente(08/2018) a versão mais atual estável é a 3.1.0)

    1- Definindo a marcação VSM na view

    Vamos definir o código abaixo no arquivo MainPage.xaml :

    No código estamos definindo duas views Entry vinculadas a propriedade IsToggled de uma view Switch de forma a podermos habilitar e desabilitar a propriedade Enabled das views Entry.

    Vamos agora aplicar a marcação do VSM na segunda view Entry:

    Para anexar a marcação VSM na segunda view Entry, separe a view Entry nas tags inicial(<Entry...>) e final(</Entry>) e em seguida, insira as tags VisualStateManager.VisualStateGroups entre essas tags:

    ...
    <Entry IsEnabled="{Binding Source={x:Reference EntryEnabled}, Path=IsToggled}">
        <VisualStateManager.VisualStateGroups>

        </ VisualStateManager.VisualStateGroups>
    </Entry>
    ...

    A propriedade VisualStateGroups é uma propriedade anexável definida pela classe VisualStateManager. É assim que a propriedade VisualStateGroups é anexada ao objeto Entry.

    A propriedade VisualStateGroups é do tipo VisualStateGroupList, que é uma coleção de objetos VisualStateGroup. Nas tags VisualStateManager.VisualStateGroups, vamos incluir um par de tags VisualStateGroup para cada grupo de estados visuais que você desejamos incluir:

    ...
    <Entry IsEnabled="{Binding Source={x:Reference EntryEnabled}, Path=IsToggled}">
        <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">

                </VisualStateGroup>
        </ VisualStateManager.VisualStateGroups>
    </Entry>
    ...

    A tag VisualStateGroup tem um atributo x:Name indicando o nome do grupo.

    Nota : A classe VisualStateGroup define uma propriedade Name que também pode ser usada da seguinte forma:  <VisualStateGroup Name="CommonStates">

    A classe VisualStateGroup define uma propriedade denominada States, que é uma coleção de objetos VisualState.

    A propriedade States é a propriedade de conteúdo de VisualStateGroups, portanto, você pode incluir as tags VisualState diretamente entre as tags VisualStateGroup.

    ...
    <Entry IsEnabled="{Binding Source={x:Reference EntryEnabled}, Path=IsToggled}">
       <VisualStateManager.VisualStateGroups>
              <VisualStateGroup x:Name="CommonStates">
                  <VisualState x:Name="Normal">

                  </VisualState>
                  <VisualState x:Name="Focused">

                 </VisualState>
                 <VisualState x:Name="Disabled">

                </VisualState>

             </VisualStateGroup>
       </ VisualStateManager.VisualStateGroups>
    </Entry>
    ...

    O VisualState define uma propriedade denominada Setters, que é uma coleção de objetos Setter. Estes são os mesmos objetos Setter que você usa em um objeto Style.

    A propriedade Setters não é a propriedade de conteúdo do VisualState, portanto, é necessário incluir tags de elemento de propriedade para a propriedade Setters:

    ...
    <Entry IsEnabled="{Binding Source={x:Reference EntryEnabled}, Path=IsToggled}">
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal">
                            <VisualState.Setters>
                            </VisualState.Setters>
                        </VisualState>
                        <VisualState x:Name="Focused">
                            <VisualState.Setters>
                            </VisualState.Setters>
                        </VisualState>
                        <VisualState x:Name="Disabled">
                            <VisualState.Setters>
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </ VisualStateManager.VisualStateGroups>
    </Entry>
    ...

    Agora, para concluir podemos inserir um ou mais objetos Setter e implementar cada funcionalidade definida nos pares de tags Setters :

    ...
     <Entry IsEnabled="{Binding Source={x:Reference EntryEnabled}, Path=IsToggled}">
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CommonStates">
                        <VisualState x:Name="Normal">
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor" Value="LigthGreen" />
                            </VisualState.Setters>
                        </VisualState>
                        <VisualState x:Name="Focused">
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor" Value="LigthYellow" />
                                <Setter Property="FontSize" Value="36" />
                            </VisualState.Setters>
                        </VisualState>
                        <VisualState x:Name="Disabled">
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor" Value="LigthBlue" />
                                <Setter Property="TextColor" Value="White" />
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </ VisualStateManager.VisualStateGroups>
    </Entry>
    ...

    Cada tag Setter indica o valor de uma propriedade específica para um estado específico. (Qualquer propriedade referenciada por um objeto Setter deve ser apoiada por uma propriedade bindable.)

    Executando o projeto iremos obter o seguinte resultado:

    Na próxima parte do artigo veremos a segunda abordagem de implementação do VSM usando estilos.

    Pegue o código do projeto compartilhado aqui:  XF_VSM1.zip

    "Porque Deus amou o mundo de tal maneira que deu o seu Filho unigênito, para que todo aquele que nele crê não pereça, mas tenha a vida eterna."
    João 3:16

    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