Animações com storyboard para estados visuais (XAML)

Estados visuais são uma técnica pela qual a mudança do estado de um controle também altera a interface do usuário, carregando modelos de controle XAML para o estado atual. O modelo de estado visual dá ao usuário um feedback do estado atual da interface, além de manter a separação entre lógica e design, que é usada pelos controles XAML. Para mudar as propriedades do estado visual, defina um conjunto de animações de storyboard em XAML. As animações dos estados visuais usam a mesma sintaxe XAML que qualquer animação de storyboard. No entanto, há algumas práticas recomendadas sobre como as animações devem ser definidas para que sejam adequadas a determinado estado visual. As animações para estados visuais devem ser instantâneas (duração zero) ou bastante rápidas, durando menos de um segundo. É importante também criar o conjunto de animações usado nos estados visuais para que qualquer alteração relacionada a estado seja revertida para seu valor original quando esse estado não for mais aplicável.

Mapa: Como este tópico está relacionado aos outros? Veja:

Animações de duração zero

Sempre que possível, use animações de duração zero para aplicar alterações de propriedade que fazem parte de um estado visual. Uma animação com duração zero tem a garantia de ser uma animação independente, além de ter impacto mínimo sobre o desempenho do thread da interface do usuário. Isso afeta a capacidade de resposta do controle e do aplicativo que o utiliza.

Ocasionalmente, uma animação de estado visual pede uma animação de transformação de conversão, o que não é bom em casos de duração zero. Porém, procure manter a duração curta (não mais que cerca de um segundo) porque os usuários não interagem facilmente com elementos em movimento. Para uma duração diferente de zero, a animação passa a ser dependente; portanto, a propriedade animada torna-se um fator importante. Pense também na possibilidade de criar esses tipos de estados usando a VisualTransition com uma duração, mas que seja igual a zero na animação de estado visual de destino.

Para saber mais sobre as implicações de uma animação dependente e quais animações são consideradas dependentes, veja a seção "Animações dependentes e independentes" de Animações de storyboard.

Criando estados visuais que restauram os valores originais

Para estados visuais, o FillBehavior aparente de uma animação de storyboard é diferente de como eles se comportariam se você os aplicasse diretamente a uma propriedade de elemento da interface do usuário. Se um estado visual for alterado para outro estado, todas as alterações de propriedade aplicadas pelo estado visual anterior e suas animações serão cancelados, mesmo se o novo estado visual não aplicar especificamente uma nova animação a uma propriedade. Por outro lado, uma animação de storyboard que direciona diretamente uma propriedade da interface do usuário do aplicativo tem um comportamento HoldEnd. Para saber mais, veja Animações de storyboard.

Para muitas alterações de estado visual, você só precisa definir um novo estado visual vazio (sem animações e sem nenhum valor Storyboard). Sua lógica de controle pode invocar o estado visual vazio para desativar as animações aplicadas por outros estados visuais no mesmo VisualStateGroup. Por exemplo, muitos modelos de controle têm um estado chamado "Normal" no VisualStateGroup "CommonStates", que não tem um valor Storyboard. A lógica de controle pode ir para o estado "Normal" para cancelar as outras animações de estado visual no mesmo grupo como "PointerOver", "Disabled" etc.

Observação  Quando um controle vai para um estado visual vazio, as propriedades do controle usam os valores de modelo originais ou outros padrões, a menos que o XAML da definição da interface do usuário tenha um valor ou o código do aplicativo o altere no tempo de execução. Mais precisamente, quando a animação do valor da propriedade é desabilitada, o valor é reavaliado de acordo com a precedência de valor de propriedade de dependência. Para saber mais sobre esse conceito, veja Visão geral de propriedades de dependência.

Estados visuais para intervenção do usuário relacionadas a ponteiro

A maioria dos controles que definem estados visuais e que podem ser selecionados ou invocados de alguma maneira possui um grupo visual primário chamado "CommonStates". No "CommonStates", você geralmente vê estes três estados nomeados:

  • "Normal"
  • "PointerOver"
  • "Pressed"
  • "Disabled"

"Normal" é o estado para quando o controle não está pressionado, não está desabilitado e não tem um ponteiro sobre sua área de teste de pressionamento. "PointerOver" e "Pressed" geralmente são estados que duram um período relativamente curto de tempo e são vinculados a ações do usuário.

"Disabled" é usado quando o valor de IsEnabled é false ou outras propriedades como IsReadOnly declaram que o controle não pode ser usado. Essas propriedades geralmente são definidas pelo código do apliativo. A lógica do seu aplicativo pode desabilitar controles para contextos em que o usuário deve usar algum outro controle, mas você opta por não ocultar o controle de desabilitação totalmente.

Na maioria dos casos, se você estiver trabalhando com um estado visual, estará modificando um design existente a partir da cópia do modelo inicial ou a partir do modelo padrão da classe de controle que está usando como classe base. Você pode usar esses comportamentos de design existentes como diretrizes para o que cada um dos estados visuais "CommonStates" deve mostrar para o usuário. Se você ainda tiver dúvidas de design relacionadas a esses estados visuais ou se estiver criando um modelo que não tem muito em comum com outros modelos existentes e precisar de orientação, veja Diretrizes de resposta visual e Respondendo à interação do usuário. As entradas por toque e mouse geram eventos de ponteiro. No nível do estado visual, esses modos de interação geralmente não são diferenciados.

Indicando o foco visual

Um dos aspectos mais importantes da interatividade e do estado que um controle deve fornecer é uma forma de o usuário saber quando o controle tem o foco em uma interface do usuário. Um controle com foco é o único controle que pode aceitar a entrada do teclado, sendo assim importante que o usuário saiba que uma área de texto da interface está com o foco para essa finalidade. Além disso, por motivos de acessibilidade, é importante identificar o foco mesmo para controles que não usam a entrada do teclado como entrada de texto. Por exemplo, controles como botões devem oferecer suporte a um modo de invocação para que uma tecla do teclado (geralmente Espaço ou Enter) possa executar a mesma ação que um toque ou clique no botão. Se isso for feito corretamente, os usuários podem usar a tecla Tab e outras teclas para interagir com a interface do usuário sem usar o toque ou o mouse. Para saber mais sobre por que isso é importante, veja Implementando a acessibilidade pelo teclado.

Um estado visual comum usa um Rectangle que inicialmente não é visível para atuar como o indicador de foco (Opacity="0"). O Rectangle é um filho imediato da raiz do modelo, que geralmente é uma das classes de painel. Certifique-se de que o Rectangle usa um Stroke estreito, que só cubra áreas de preenchimento ao redor do conteúdo do controle quando ele tiver o foco. Caso contrário, um controle com o foco pode ocultar conteúdo importante do usuário. Em um design de estado visual comum, os estados fazem parte de um VisualStateGroup chamado "FocusStates" e há dois estados chamados "Focused" e "Unfocused".

No VisualStateGroup "FocusStates", você deve definir um estado visual "PointerFocused" vazio separado. O indicador de foco não deve aparecer se for um ponteiro que direciona o foco para um controle. O indicador de foco deve mostrar o foco específico de elemento conforme controlado por um usuário usando a sequência de tabs ou o foco programático inicial quando a página do aplicativo é carregada pela primeira vez.

Mais estados visuais

  • Controles como CheckBox definem um VisualStateGroup "CheckStates". No modelo padrão, os estados nomeados desse grupo são: "Checked", "Unchecked", "Indeterminate".
  • Os controles que permitem iniciar uma operação de arrastar e soltar têm um grupo chamado "DragStates" com vários estados internos. Por exemplo, ao editar uma cópia do modelo de controle GridViewItem, você vê esses estados no XAML de partida.
  • Os controles que oferecem suporte à seleção de itens têm vários estados relacionados à seleção nos modelos de seus tipos de item. Os nomes dos grupos e estados variam de acordo com o controle. Você pode vê-los se editar uma cópia do modelo.
  • Alguns projetos do Microsoft Visual Studio no Windows 8 para aplicativos definem os estados visuais dos estados de exibição display-area. Os modelos do Windows 8.1 não fazem mais isso.

Um XAML de exemplo

Veja a seguir um XAML de exemplo de um conjunto comum de estados visuais em um "CommonStates" VisualStateGroup. Isso foi retirado diretamente dos modelos padrão de Tempo de Execução do Windows para controles e outros elementos de interface do usuário. Você pode editar uma cópia do XAML do modelo padrão caso deseje personalizar alguns dos botões da AppBar em seu aplicativo. Como mostrado aqui, o XAML está um pouco editado no modelo completo, com as reticências ... mostradas porque você não precisa ver o arquivo inteiro ou todos os estados visuais para entender os princípios básicos.


<Style x:Key="BackButtonStyle" TargetType="Button">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <Grid x:Name="RootGrid">
...
          <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Normal"/>
...
              <VisualState x:Name="Disabled">
                <Storyboard>
                  <ObjectAnimationUsingKeyFrames 
                    Storyboard.TargetName="RootGrid"
                    Storyboard.TargetProperty="Visibility"
                  >
                    <DiscreteObjectKeyFrame Value="Collapsed" KeyTime="0"/>
                  </ObjectAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
            </VisualStateGroup>
...
          </VisualStateManager.VisualStateGroups>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

  • O estado "Disabled" está aplicando uma animação de storyboard à propriedade Visibility. A propriedade Visibility recebe uma enumeração, portanto, para animá-la, você precisa usar um DiscreteObjectKeyFrame para definir o Value como uma constante de enumeração específica da enumeração Visibility. A aplicação de uma alteração ao Visibility de um elemento de composição ou eventualmente ao controle inteiro é muito comum em definições de estado visual.
  • Observe como o estado "Normal" está vazio. A lógica de controle pode carregar esse estado para cancelar o estado visual chamado "Desabilitado" e restaurar a Visibility para seu valor definido pelo modelo, que é o padrão Visible.

Lógica de controle para usar estados visuais

A lógica de controle comum usa diversos eventos de entrada e propriedades de status para determinar qual estado visual dos vários grupos de estados visuais deve estar ativo em um controle no tempo de execução.

  • Os estados visuais relacionados a ponteiros (por exemplo, "PointerOver" e "Pressed") podem ser alterados através da manipulação dos eventos de entrada (os eventos PointerEntered e PointerExited). Geralmente, os controles manipulam esses eventos substituindo os manipuladores internos OnPointerEntered e OnPointerExited.
  • "Disabled" pode ser chamado por IsEnabledChanged ou manipuladores de alterações em outras propriedades específicas de controle como IsReadOnly.
  • Estados visuais de foco podem ser alterados através da manipulação dos eventos GotFocus e LostFocus. Geralmente, os controles manipulam esses eventos substituindo os manipuladores internos OnGotFocus e OnLostFocus. Para OnGotFocus, a lógica de controle deve verificar o FocusState para ver se ele é o ponteiro que causou a alteração de foco e, se for, usar o estado "PointerFocused" em vez de "Focused".

VisualTransition

Além de definir os diversos estados visuais nomeados, um VisualStateGroup também pode ter uma coleção de elementos VisualTransition. Um VisualTransition define um comportamento de animação que é executado quando uma alteração de estado ocorre (quando GoToState é chamado). Você verá uma transição visual quando os estados novo e velho envolvidos na alteração de estado tiverem diferenças de valor de propriedade e houver um VisualTransition referenciando os estados nomeados antigo/novo como um valor From ou To.

Para um VisualTransition, você geralmente não tem uma duração zero, pois a finalidade de uma transição visual é mostrar uma alteração ao longo do tempo à medida que os estados visuais mudam.

Em termos gerais, há duas maneiras de definir um VisualTransition: usando um Storyboard específico que define uma ou mais propriedades em que você aplica uma animação de storyboard programada ou contando com o comportamento de GeneratedDuration.

Um Storyboard específico usa basicamente as técnicas descritas neste tópico e no tópico Animações de storyboard, com exceção de que animações de duraçã ozero não são usadas nesse Storyboard . As propriedades que você anima na transição visual não têm propriedades to que mudam entre os estados visuais envolvidos na transição.

Um comportamento GeneratedDuration simplesmente precisa ter um valor diferente de zero para GeneratedDuration. Em seguida, o sistema de estados visuais determina quais propriedades estão mudando de valor entre os estados antigo e novo e gera uma animação interpolada entre os valores alterados com a duração especificada. O comportamento GeneratedDuration só funciona para valores que podem ser interpolados pela animação: valores Double, Point ou Color.

Para um VisualTransition, você define os estados visuais entre os quais o VisualTransition deve fazer a transição. From referencia o estado antigo e To referencia o estado novo. Se você tiver um valor para From, mas não para To (ou vice-versa), o valor não definido será interpretado como se referenciasse qualquer outro estado do mesmo grupo de estados visuais. Um VisualTransition sem From nem To não faz nada.

Você pode usar um comportamento de interpolação diferente do padrão de interpolação linear definindo um valor para GeneratedEasingFunction. Para obter uma lista das possíveis funções de easing que você pode usar e das fórmulas matemáticas de função ao longo do tempo que cada uma representa, veja Animações de quadro chave e animações com função de easing.

Tome cuidado com o comportamento GeneratedDuration. Como não é uma animação de duração zero por definição, você pode acidentalmente criar uma animação dependente em propriedades que estão mudando e comprometer o desempenho do controle ou do aplicativo.

As animações VisualState são executadas sempre que um estado é inserido, mesmo quando o controle aparece pela primeira vez. As animações VisualTransition não fazem isso, não há transição para o primeiro estado carregado, mesmo se houver uma transição que especifica o primeiro estado como seu To.

Modificando cópias de modelo

Ferramentas, como o Visual Studio, fornecem uma maneira fácil de remodelar um controle começando com uma cópia do modelo padrão do Tempo de Execução do Windows e colocando-a em algum lugar em que pode ser modificada e usada pelo seu aplicativo e projeto. Qualquer estado visual de um controle também está incluído nesse modelo, em um nó XAML VisualStateManager.VisualStateGroups, logo abaixo do elemento raiz do conteúdo do modelo, no setter de estilo Template principal. Sempre que você estiver trabalhando com uma cópia de modelo, certifique-se de reproduzir todos os estados visuais nomeados e grupos de estados visuais que o modelo tinha inicialmente. Se você não fizer isso, o controle poderá não ter estados visuais importantes que informam o usuário de interações na experiência da interface do usuário. A lógica do controle tentará chamar GoToState para acessar os estados nomeados esperados que não existem em seu modelo XAML personalizado e o comportamento do VisualStateManager é que o controle permanecerá no último estado visual carregado corretamente. Por exemplo, o controle pode ficar preso em um estado "PointerOver", mesmo quando o ponteiro não está mais sobre o controle, caso você não forneça o estado "Normal" que é geralmente chamado quando o ponteiro existe.

Para saber mais sobre como modificar modelos de controle, veja Guia de início rápido: modelos de controle.

Não use estados visuais de grupos diferentes para animar a mesma propriedade

A maioria dos modelos de estado visual tem mais de um grupo de estados visuais, sendo cada grupo responsável por representar o estado de um conjunto de condições que são exclusivas dentro desse grupo. Por exemplo, um controle pode ter um grupo que responde a eventos de ponteiro, um conjunto que responde ao foco atual do teclado e um estado para entrada de texto. Dessa forma, o controle está realmente usando vários estados ao mesmo tempo. Quando há estados de grupos diferentes modificando a mesma propriedade como uma ação de estado visual, o valor a ser usado torna-se indeterminado, pois ele agora depende do estado que foi informado por último. Não faça isso. Talvez seja necessário inserir elementos bastante relacionados em seu modelo de controle para ter certeza de que os grupos de estados visuais diferentes utilizem elementos diferentes ao animarem propriedades que afetam o estado visual do controle.

Usando a biblioteca de animação em estados visuais

A biblioteca de animação do Windows Runtime inclui várias animações de tema. Essas animações de tema são animações de uma ou mais propriedades de tipos de interface do usuário XAML do Tempo de Execução do Windows. Alguns dos controles do Windows Runtime XAML incluem animações de tema dentro dos estados visuais padrão. Elas podem ser encontradas em dois possíveis lugares:

  • Como uma das animações do VisualState.Storyboard para um ou mais estados visuais do controle. Nesse local, a animação do tema é executada quando esse estado visual é usado (quando a lógica do controle chama GoToState referenciando esse estado).
  • Como uma das animações do VisualTransition.Storyboard, dentro de VisualStateGroup.Transitions. Nesse local, a animação do tema é executada quando o gerenciador do estado visual executa a transição entre os dois estados nomeados relevantes.

Se você estiver usando a técnica típica de inicialização com uma cópia de XAML do modelo de controle padrão que você obteve com Editar Modelo/Editar uma Cópia no Microsoft Visual Studio, poderá ver as animações de tema na sua cópia de inicialização. Normalmente, você não tem que remover as animações de tema de um modelo de controle. As animações de tema estão lá deliberadamente, não apenas para dar uma aparência melhor para aquele determinado controle XAML, mas também para melhorar a experiência geral do usuário do Windows.

Para usar uma animação de tema, você deverá direcioná-la a uma determinada parte dentro do modelo. Para fazer isso, defina o atributo TargetName da animação do tema usando uma cadeia de caracteres que é o x:Name de uma das partes do modelo definida em outro lugar do modelos (essas são as partes que definem o modelo inicial). As animações do tema direcionam propriedades específicas inerentemente e, às vezes, direcionam mais de uma propriedade relacionada ao fundo. Como não é imediatamente óbvio para quais propriedades uma animação de tema está direcionada; também não é óbvio para quais partes você deve direcionar pelo TargetName, de modo que as propriedades que estão sendo animadas e esse destino se alinhem.

Importante  Não use Storyboard.TargetName ou Storyboard.TargetProperty quando estiver direcionando para uma animação de tema. Esse modelo de direcionamento colide com o atributo TargetName não anexado e com a natureza inerente do direcionamento de propriedades pelas animações de tema.

Quando os estilos e modelos padrão de um controle usam uma animação de tema em particular, isso é listado nos tópicos "Animação ..." que documentam como e quando usar as animações da biblioteca específica. Por exemplo, se você olhar as Ações do ponteiro da animação, verá uma seção "Animações de ponteiro no comportamento de controle do Windows Runtime padrão", onde observa-se que ListViewItem e GridViewItem estão incluindo um PointerDownThemeAnimation em um dos seus estados visuais do modelo padrão. Você poderá observar isso na documentação de estilos e modelos dos controles. Por exemplo, os estilos e modelos ListViewItem mostram para você exatamente onde o PointerDownThemeAnimation existe na seção "Estilo padrão" que mostra o XAML completo.

As animações de tema geralmente não são de duração zero, mas são curtas, normalmente menos de 2 segundos. Elas são cuidadosamente criadas para direcionar a propriedades que não resultam em animações dependentes.

A maioria das animações de tema não possui propriedades diferentes de TargetName e o que herdam de Timeline. Mas algumas animações de tema têm propriedades adicionais. Por exemplo, PopInThemeAnimation tem uma FromHorizontalOffset propriedade que modifica onde a animação começa posicionalmente. Modifique-as com cuidado porque elas estão usando os padrões que apresentam uma experiência do usuário do Windows coesiva e mudar o comportamento radicalmente poderia ser tão prejudicial quanto remover a animação de tema inteira.

Conforme afirmado anteriormente, alguns controles têm animações de tema presentes por padrão nos seus estados visuais ou nas transições visuais. Mas, em alguns casos, as propriedades de uma animação de biblioteca que um controle usa para o seu estilo ou estados visuais podem receber estilo sem ter que substituir completamente o modelo do controle. Isso é ativado mudando o valor da propriedade TemplateSettings do controle. Veja aqui uma lista dos controles onde você pode modificar as animações de tema fora dos modelos, fazendo referência {a à propriedade que oferece suporte:

Há outro tipo de animação na biblioteca de animações chamada transição de tema. Ele á usada nas propriedades *Transitions para controles específicos ou talvez na propriedade UIElement.Transitions. Essas propriedades não estão dentro dos estados visuais, mas as transições de tema são relevantes para controlar estilos em geral porque você geralmente define as propriedades *Transitions no padrão (chave implícita) Style para um Control ou talvez para outros elementos da interface do usuário, como um TextBlock. Algumas das TemplateSettings listadas anteriormente afetam as transições de tema. Para obter mais informações sobre como usar as transições de tema, consulte Animando sua interface do usuário ou Guia de início rápido: Animando sua interface do usuário usando as animações da biblioteca.

Estados visuais para cenários não relacionados a modelos de controle

O uso de estados visuais para ajudar a definir estados atuais da interface do usuário não se limita a cenários de modelagem de controles. Você pode usar estados visuais sempre que quiser aplicar um conjunto de alterações de propriedade que só deve ser aplicado durante uma condição detectável. Por exemplo, você pode usar estados visuais para páginas do seu aplicativo para detectar os estados de aplicativo ou de janela e alterar as propriedades de layout em resposta. Os estados visuais para cenários não relacionados a modelos precisam de código para monitorar alterações de estado e invocar o estado visual correto no elemento da interface do usuário que usa os estados. Isso pode envolver a manipulação de eventos que fazem parte do modelo de aplicativo, como eventos na Window, eventos de dispositivo de sistema que detectam alterações de orientação do monitor ou alterações de resolução, ou manipuladores de ativação no Application. Alguns desses conceitos se sobrepõem ao modelo de aplicativo e ao modo como o aplicativo pode controlar os estados de exibição; para saber mais, veja Guia de início rápido: criando aplicativos para diferentes tamanhos de janela.

Tópicos relacionados

Respondendo à interação do usuário
Animações de storyboard
Mapa de criação de aplicativos em C#, C++ ou VB
Visão geral das propriedades de dependência
Animações de quadro chave e animações com função de easing
Guia de início rápido: modelos de controle
VisualStateManager
VisualState
VisualTransition
Storyboard
Storyboard.TargetProperty

 

 

Mostrar:
© 2015 Microsoft