Aplicando animações de storyboard a vários objetos XAML

Applies to Windows and Windows Phone

A seguir estão instruções de como evitar a criação de várias animações storyboard e de como aplicar a mesma storyboard a vários objetos.

Analise esta página XAML de um aplicativo, exibindo uma grade de imagens de teclado numérico. Quando o usuário toca em um desses botões, a ideia é animá-lo para fazer parecer que ele está sendo movido.

Um arquivo XAML com vários botões: você quer mesmo criar uma animação de storyboard para cada um deles?

Como vimos no tópico Aplicando capa e animação a um botão, diferentemente do iOS em que é possível variar parâmetros como a opacidade ao longo do tempo em um bloco de animações, o Windows 8 usa objetos de storyboard. Se houver vários objetos XAML semelhantes na tela, por exemplo, nossa grade de botões, você poderá imaginar se é necessário criar uma storyboard exclusiva para cada um deles. A boa notícia é que isso não é necessário: e a seguir estão as instruções de como aplicar a mesma animação a vários objetos.

Observação   Lembre-se de que no Windows 8 uma storyboard é uma animação, e não uma maneira de criar layout de seu aplicativo como no Xcode.

O segredo é mudar via programação a propriedade TargetName da storyboard, como mostrará o exemplo a seguir.

Definindo a storyboard

Primeiro, defina a animação de storyboard. Você pode usar Blend ou defini-la manualmente em XAML. Para obter um exemplo usando Blend, veja Aplicando capa e animação a um botão. Se você usar Blend, remova qualquer propriedade TargetName, senão a animação será aplicada somente a esse destino específico. A seguir está um exemplo:


    <Page.Resources>
        <Storyboard x:Name="TapAnimation">
			<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" >
				<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
				<EasingDoubleKeyFrame KeyTime="0:0:0.05" Value="0.95"/>
				<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="1"/>
			</DoubleAnimationUsingKeyFrames>
			<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)" >
				<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
				<EasingDoubleKeyFrame KeyTime="0:0:0.05" Value="0.95"/>
				<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="1"/>
			</DoubleAnimationUsingKeyFrames>
		</Storyboard>
    </Page.Resources>

Lembre-se de adicionar uma marca <RenderTransform> a qualquer objeto XAML que o seu storyboard mudará, bem como um espaço reservado à transformação específica que está sendo animada, caso contrário, o aplicativo emitirá uma exceção. A seguir está um exemplo de um objeto Image pronto para que o storyboard seja aplicado:


 <Image x:Name="myImage" Width="256" Height="160" RenderTransformOrigin= "0.5,0.5" >
                        <Image.RenderTransform>
                            <CompositeTransform/>
                        </Image.RenderTransform>
                    </Image>

Observação  O uso da propriedade RenderTransformOrigin= "0.5,0.5" garante que qualquer animação seja centralizada ao redor do meio do objeto.

Aplicando a storyboard

Depois, associe a storyboard a um objeto e dispare-a conforme necessário. Há uma ressalva - não é possível mudar a propriedade TargetName enquanto a animação está sendo executada, senão o aplicativo emitirá uma exceção. Para impedir isso, chame Stop() antes de mudar o destino.

Dica  A chamada de GetCurrentState() pode detectar se um storyboard está em execução no momento.

A seguir está o código para disparar a animação para um objeto Image específico. Por exemplo, esse código pode ser em resposta ao toque da imagem usando um evento PointerPressed. É simplesmente mais fácil aplicá-lo a Button, usando um evento Click.


 // Add using Windows.UI.Xaml.Media.Animation;
            TapAnimation.Stop();
            TapAnimation.SetValue(Storyboard.TargetNameProperty,"myImage");
            TapAnimation.Begin();

Essa abordagem é ainda mais útil ao gerar um novo nome de destino automaticamente a partir do controle que disparou o evento, como este:


  private void someImages_PointerPressed(object sender, PointerRoutedEventArgs e)
        {
            TapImage.Stop();
            TapImage.SetValue(Storyboard.TargetNameProperty, (sender as Image).Name);
            TapImage.Begin();
        }

Aqui o objeto Image em que o usuário tocou cria o evento, e usamos seu nome como destino. Se todas as imagens na página gerarem o mesmo evento quando tocadas, elas serão todas animadas com a mesma storyboard. Assim, em nosso exemplo de teclado numérico, cada tecla será animada e só precisamos criar uma storyboard.

Observação  Talvez você não tenha visto como teclado antes: ele executa uma conversão no emissor para torná-lo Image.

Vários botões, e um manipulador de eventos

Com um aplicativo com vários botões semelhantes, faz sentido ter um manipulador de eventos mestre, em vez de um manipulador de eventos para cada botão. Cada botão pode usar o mesmo evento de clique, mas precisamos de uma maneira de diferenciar os botões no código: este é um bom lugar para usar tags

Como no iOS, cada controle ou objeto pode ter uma marca: um valor que pode ser usado para identificá-los exclusivamente. Por exemplo, em nosso exemplo de teclado numérico, poderíamos definir os botões como neste XAML: observe como os botões estão praticamente idênticos, mas são diferentes no valor da marca.


	<Button Content="1" HorizontalAlignment="Left" Margin="446,78,0,0" VerticalAlignment="Top" Width="120" Height="120" FontSize="48" FontWeight="Bold" Click="Button_Click" Tag="1">
    		<Button.Background>
    			<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    				<GradientStop Color="Black"/>
    				<GradientStop Color="#FF838383" Offset="1"/>
    			</LinearGradientBrush>
    		</Button.Background>
    	</Button>
        <Button Content="2" HorizontalAlignment="Left" Margin="446,543,0,0" VerticalAlignment="Top" Width="460" Height="120" FontSize="48" FontWeight="Bold" Click="Button_Click" Tag="2">
    		<Button.Background>
    			<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    				<GradientStop Color="Black"/>
    				<GradientStop Color="#FF838383" Offset="1"/>
    			</LinearGradientBrush>
    		</Button.Background>
    	</Button>
        <Button Content="3" HorizontalAlignment="Left" Margin="446,393,0,0" VerticalAlignment="Top" Width="120" Height="120" FontSize="48" FontWeight="Bold" Click="Button_Click" Tag="3">
    		<Button.Background>
    			<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
    				<GradientStop Color="Black"/>
    				<GradientStop Color="#FF838383" Offset="1"/>
    			</LinearGradientBrush>
    		</Button.Background>
    	</Button>

Todos os botões apontam para o mesmo manipulador de eventos, Button_Click. A seguir está como podemos ler o valor da marca e reagir apropriadamente no manipulador:


        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var tag = (sender as Button).Tag;

            int t = Convert.ToInt16(tag);

            switch (t)
            {
                case 0: break;
                case 1: break;
                case 2: break;
                default: break;
            }
        }

Tópicos relacionados

Trabalhando com animações via programação
Introdução: animação
Como criar interfaces de usuário usando o XAML e o Expression Blend
Animações com storyboard

 

 

Mostrar:
© 2015 Microsoft