Quando eu vi uma pergunta de um usuário nos forums do MSDN sobre animação de um user control para dar o efeito de saída ao clicar um botão, eu pensei que esta seria uma excelente oportunidade de criar uma série de posts aqui no blog, mostrando diversas maneiras de fazê-lo.
Apesar de colocar as alternativas aqui, algumas podem não ser tão boas: este post onde eu ponho animação no code behind, apesar de ser fácil de implementar, tem algumas desvantagens:
- O código da animação é posto no code behind, uma técnica que eu não gosto. Eu nao acho que o padrão MVVM deva ter zero code behind, mas eu não gosto de por código lá, a menos que seja indispensável e estritamente relacionado com a view.
- Não é design-friendly – se o designer quer mudar a animação, o código deve ser alterado.
- Não é portável – se você quer criar a mesma animação em outros lugares, o código deve ser copiado ou refatorado para ser acessado de outros lugares.
- Não é fácil de manipular – tudo é feito em código. Quaisquer mudanças, como a duração da animação deve ser alterado em código.
Temos o seguinte problema: temos um controle na janela e queremos escondê-lo quando o botão é clicado, usando uma animação, como vemos abaixo:
Para fazer isso, devemos criar uma animação para o controle, do tipo RenderTransform e animá-la. Podemos fazer tudo em código desta maneira: no clique do botão, criamos a transformação, adicionamos ao controle e animamos ela:
private void Button_Click(object sender, RoutedEventArgs e)
{
// create the transformation and add it to the control
var translate = new TranslateTransform(0, 0);
gridLogin.RenderTransform = translate;
// create the animation and start it
var da = new DoubleAnimation(0, -ActualWidth, new Duration(TimeSpan.FromMilliseconds(1000)));
translate.BeginAnimation(TranslateTransform.XProperty, da);
}
Este código tem muitos inconvenientes:
- Ele só pode ser aplicado ao nosso controle. Para adicioná-lo a outro controle, devemos copiar o código.
- A duração da animação é 1 segundo – a duração é fixa.
- Somente anima da direita para a esquerda.
Nesta primeira fase, refatoraremos o código para deixá-lo mais genérico:
public enum AnimationType
{
Right,
Left,
Up,
Down
}
private void Button_Click(object sender, RoutedEventArgs e)
{
AnimateControl(gridLogin, TimeSpan.FromMilliseconds(1000), AnimationType.Left);
}
private void AnimateControl(UIElement control, TimeSpan duration, AnimationType type)
{
double xEnd = 0;
double yEnd = 0;
if (type == AnimationType.Left)
xEnd = -ActualWidth;
else if (tipo == AnimationType.Right)
xEnd = ActualWidth;
else if (tipo == AnimationType.Up)
yEnd = -ActualHeight;
else if (tipo == AnimationType.Down)
yEnd = ActualHeight;
// create the transformation and add it to the control
var translate = new TranslateTransform(0, 0);
control.RenderTransform = translate;
// create the animation and start it
if (tipo == AnimationType.Left || tipo == AnimationType.Right)
{
var da = new DoubleAnimation(0, xEnd, new Duration(duration));
translate.BeginAnimation(TranslateTransform.XProperty, da);
}
else
{
var da = new DoubleAnimation(0, yEnd, new Duration(duration));
translate.BeginAnimation(TranslateTransform.YProperty, da);
}
}
Apesar do código ser maior, ele é mais genérico e permite ser reutilizado. Podemos usar qualquer controle, configurar a deuração e a direção da animação. Ainda não é o idela, mas é melhor que o código anterior, não reutilizável. Nos próximos posts veremos outras maneiras de fazer isso. Até lá!