12

Feb

[Windows 8] Animare i controlli in XAML / C#

Ciao a tutti!

Questo è il mio primo post, pertanto mi sembra doveroso dare il benvenuto a tutti quelli che vorranno seguirmi in questa nuova esperienza, oltre a ringraziare DoNetLombardia per l’opportunità di far parte della loro bella comunità.

Ero molto indeciso su quale argomento trattare per primo su questo blog, ma recentemente ho avuto modo di constatare che molti sviluppatori che stanno creando applicazioni per lo Store di Windows 8, spesso si arenano sul discorso delle animazioni dell’interfaccia; quindi ho deciso che prima di parlare di argomenti un po’ più complessi, mi piacerebbe illustrare velocemente come è facile animare un oggetto in XAML + C# in un’app per Windows 8.

Il nuovo WinRT mette a disposizione dei semplici oggetti che permettono di animare moltissime proprietà degli elementi della UI (bottoni, immagini ecc..) con pochissime righe di codice. Questi oggetti sono le Animations che, insieme all’oggetto Storyboard, ci permettono di far variare il valore di una proprietà in un arco di tempo predefinito e in modo molto “immediato”.

Per alcune proprietà esistono oggetti specifici, come ad esempio la ColorAnimation per il colore, mentre per altre proprietà è possibile utilizzare oggetti più generici come la DoubleAnimation, che permette di animare tutte le proprietà che hanno un valore numerico (come opacità, posizione ecc.). Per capire meglio di cosa stiamo parlando non c’è niente di meglio che fare un esempio pratico: vediamo dunque come poter spostare un bottone contenuto in un Canvas di 100 pixel verso destra in un tempo di 1 secondo.

Per prima cosa aggiungiamo gli elementi dell’interfaccia nello XAML della pagina:

    
        Width="100"
        Height="100"
        Canvas.Left="50"
        Canvas.Top="50"/>

      

 

Poi, dato che le animazioni sono di fatto degli oggetti, andiamo nel codice per dichiarare ed istanziare i 2 oggetti che ci servono per animare il bottone, ovvero una DoubleAnimation e una Storyboard, che si trovano entrambe nel namespace Windows.UI.Xaml.Media.Animation, e lo facciamo direttamente nell’evento OnNavigatedTo

 

 
//istanzio i 2 oggetti
Storyboard myStoryboard = new Storyboard();
DoubleAnimation horizontalAnimation = new DoubleAnimation();
Una volta istanziati dobbiamo dire alla nostra animation qual’è l'oggetto da animare e quale proprietà in particolare vogliamo modificare. Nel nostro caso la proprietà Canvas.Left:

 

 
//utilizzo i metodi della classe Storyboard per impostare 
//il target dell'animazione e la proprietà che andrà animata
Storyboard.SetTarget(horizontalAnimation, animatedButton);
Storyboard.SetTargetProperty(horizontalAnimation, "(Canvas.Left)");
 
//poi imposto i valori dell'animazione, 
//dando come posizione di partenza la posizione attuale del bottone
//e come destinazione la posizione attuale + 100 pixel
horizontalAnimation.From = Canvas.GetLeft(animatedButton);
horizontalAnimation.To = Canvas.GetLeft(animatedButton) + 100;
 
//poi indico la durata dell'animazione
horizontalAnimation.Duration = TimeSpan.FromSeconds(1);
Infine aggiungiamo l’animazione alla storyboard e la facciamo partire tramite il metodo Begin

 

 
//infine aggiungo l'animazione alla storyboard
myStoryboard.Children.Add(horizontalAnimation);
 
//e faccio partire l'animazione
myStoryboard.Begin();
Quest’ultimo passaggio ci suggerisce che è possibile animare diversi oggetti e/o diverse proprietà contemporaneamente, aggiungendo semplicemente più oggetti di tipo animazione nella Storyboard.
A questo punto il codice completo della pagina dovrebbe assomigliare a questo:

 

 
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Media.Animation;
 
// Il modello di elemento per la pagina vuota è documentato all'indirizzo http://go.microsoft.com/fwlink/?LinkId=234238
 
namespace AnimationsDemo
{
    /// 
    /// Pagina vuota che può essere utilizzata autonomamente oppure esplorata all'interno di un frame.
    /// 
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }
 
        /// 
        /// Richiamato quando la pagina sta per essere visualizzata in un Frame.
        /// 
        /// Dati dell'evento in cui vengono descritte le modalità con cui la pagina è stata raggiunta. La proprietà
        /// Parameter viene in genere utilizzata per configurare la pagina.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
 
            //istanzio i 2 oggetti
            Storyboard myStoryboard = new Storyboard();
            DoubleAnimation horizontalAnimation = new DoubleAnimation();
 
            //utilizzo i metodi della classe Storyboard per impostare 
            //il target dell'animazione e la proprietà che andrà animata
            Storyboard.SetTarget(horizontalAnimation, animatedButton);
            Storyboard.SetTargetProperty(horizontalAnimation, "(Canvas.Left)");
 
            //poi imposto i valori dell'animazione, 
            //dando come posizione di partenza la posizione attuale del bottone
            //e come destinazione la posizione attuale + 100 pixel
            horizontalAnimation.From = Canvas.GetLeft(animatedButton);
            horizontalAnimation.To = Canvas.GetLeft(animatedButton) + 100;
 
            //poi indico la durata dell'animazione
            horizontalAnimation.Duration = TimeSpan.FromSeconds(1);
 
            //infine aggiungo l'animazione alla storyboard
            myStoryboard.Children.Add(horizontalAnimation);
 
            //e faccio partire l'animazione
            myStoryboard.Begin();
 
        }
    }
}

 

e se facciamo eseguire il progetto vedremo il bottone rosso spostarsi da sinistra verso destra per 1 secondo.

 

Una cosa importante da sapere è il modo in cui vanno specificate le proprietà quando si utilizza il metodo SetTargetProperty. Infatti se vogliamo animare un proprietà diretta dell’oggetto basta semplicemente scrivere il nome della property:

 

 
Storyboard.SetTargetProperty(myAnimation, "Opacity");

 

Mentre se dobbiamo “raggiungere” una proprietà un po’ più annidata, occorre utilizzare le parentesi tonde per far sì che il tutto funzioni. Ad esempio per animare la proprietà ScaleX del bottone, dobbiamo passare dalla RenderTransform –> CompositeTransform. Per capire meglio aggiungiamo al bottone nello XAML la trasformazione sulla X:

 

 
    
        Width="100"
        Height="100"
        Canvas.Left="50"
        Canvas.Top="50" RenderTransformOrigin="0.5,0.5">
        
            "1"/>
        
    

      

 

Per poter animare quella proprietà dobbiamo utilizzare lla stringa seguente

 

 
Storyboard.SetTargetProperty(scaleAnimation, "(Button.RenderTransform).(CompositeTransform.ScaleX)");

 

Per vedere il risultato finale aggiungiamo una nuova DoubleAnimation chiamata scaleAnimation alla storyboard, ripetendo i vari passaggi di prima:

 

 
DoubleAnimation scaleAnimation = new DoubleAnimation();
Storyboard.SetTarget(scaleAnimation, animatedButton);
Storyboard.SetTargetProperty(scaleAnimation, "(Button.RenderTransform).(CompositeTransform.ScaleX)");
 
scaleAnimation.From = 1;
scaleAnimation.To = 0.3;
scaleAnimation.Duration = TimeSpan.FromSeconds(1);
 
myStoryboard.Children.Add(scaleAnimation);

 

Alla fine potremo vedere il bottone spostarsi verso destra mentre si restringe.

 

Sperando che questo mio primo post sia stato utile a qualcuno, non mi resta che darvi appuntamento alla prossima puntata e…beh, naturalmente ogni commento e/o suggerimento è sempre ben accetto! Sorriso

 

Marcello

by Marcello Marchetti on 2/12/2013