29 mars 2024

SplashScreen : Wait and see

splashscreen de l'application Pharaon
Animation gif en 256 couleurs ne reflétant pas le rendu réel
Voici une petite méthode très simple et sans prétention pour animer un SplashScreen tout en chargeant des données. De quoi distraire l’utilisateur en beauté. N’est ce pas plus joli qu’une barre de progression ?

Ajout d’une page


Bien évidemment le splashscreen n’est qu’une image jpeg et en tout cas, à l’heure actuelle dans la version 7.5 de Windows Phone, ce n’est pas possible de l’animer. Donc tout se passe dans une simple page que j’ajoute au projet et que je nomme SplashScreen.xaml.

Modification de la page de démarrage


Il faut aussi modifier la première page appelée dans le fichier WMAppManifest.xml

    
<Tasks>
    <DefaultTask  Name ="_default" NavigationPage="SplashScreen.xaml"/>
</Tasks>

Pas de GoBack()


Enfin, dans la MainPage.xaml de votre projet, il faut penser à supprimer de l’historique de navigation la page SplashScreen.XAML. Pour cela je passe un paramètre à MainPage.xaml:

string destination = "/MainPage.xaml";
destination += String.Format("?Parametre={0}", "SplashScreen");
this.NavigationService.Navigate(new Uri(destination, UriKind.Relative));

Puis dans la méthode OnNavigatedTo de MainPage.xaml, je supprime la page via NavigationService.RemoveBackEntry();. Notez la condition e.NavigationMode == NavigationMode.New qui va examiner si c’est la première fois qu’on accède à cette page.

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    if (e.NavigationMode == NavigationMode.New)
    {
        string param = "";
        NavigationContext.QueryString.TryGetValue("Parametre", out param);
        if (param == "SplashScreen")
        {
            NavigationService.RemoveBackEntry();
        }
    }
    base.OnNavigatedTo(e);
}

Animation


Quelque soit l’animation que vous ferez dans notre chez Expression Blend préféré, il faudra que vous y placiez la même image en background que le SlashScreen.jpg ; L’utilisateur ne doit pas voir une image sauter à cause à un pixel près.
Dans votre logiciel de dessin je vous laisse détourer le fond à animer et reproduire les parties manquantes :
détourer l'image dans paint.net
Puis reconstruire le XAML :
construction de la page dans Expression Blend
Enfin j’anime la grid « Ciel » en créant un StoryBoard où j’ai simplement faire une translation en X négative.

Code-behind de SplashScreen.xaml


Côté C#, mon application va lire un flux RSS et lancer une animation. J’exécute ma méthode pour lire le Flux (celle-ci ne bloquant pas le Thread de UI) et je m’abonne à l’évènement Loaded où je lance mon storyboard (ou utilisez le ControlStoryboardAction via Blend) :

bool FluxLoaded = false;
bool StoryBoardEnded = false;
public SplashScreen()
{
    InitializeComponent();
    GetFeed(handleFeed);
    this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}

Dans la méthode Loaded, c’est parti pour le StoryBoard et je m’abonne à la fin de ce dernier :

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    this.StoryboardSplashScreen.Completed += new EventHandler(Story_Completed);
    this.StoryboardSplashScreen.Begin();
}

Le code pour lire le flux de manière asynchrone :

public void GetFeed(Action<string> doSomethingWithFeed)
{
    HttpWebRequest request = HttpWebRequest.CreateHttp("http://pharaon-magazine.fr/rss.xml");
    if (request.Headers == null)
    {
        request.Headers = new WebHeaderCollection();
    }
    request.Headers[HttpRequestHeader.IfModifiedSince] = DateTime.UtcNow.ToString();");  

    request.BeginGetResponse(asyncCallback =>
    {
        string data = null;
        try
        {
            using (WebResponse response = request.EndGetResponse(asyncCallback))
            {
                using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                {
                    data = reader.ReadToEnd();
                }
            }
            Deployment.Current.Dispatcher.BeginInvoke(() => doSomethingWithFeed(data));
        }
        catch 
        {
            FluxLoaded = true;
        }
    }
    , null);
}

Enfin, je passerai à ma MainPage.xaml dès que mon flux sera chargé. Les Thread.Sleep() sont à votre goût :

private void handleFeed(string feedString)
{
    App._FluxXML = XElement.Parse(feedString);

    FluxLoaded = true;
    //Mon animation t'hypnotise. Reste un peu:
    if (StoryBoardEnded == true)
    {
        Thread.Sleep(2000); //pour la beauté du spectacle
        ExitPage();
    }
}

private void Story_Completed(object sender, EventArgs e)
{
    StoryBoardEnded = true;
    //Ne sors que si le flux est chargé
    if (FluxLoaded == true)
    {
        Thread.Sleep(500);
        ExitPage();
    }
}

private void ExitPage()
{
    this.StoryboardSplashScreen.Completed -= new EventHandler(Story_Completed);

    string destination = "/MainPage.xaml";
    destination += String.Format("?Parametre={0}", "SplashScreen");
    this.NavigationService.Navigate(new Uri(destination, UriKind.Relative));
}

Une réflexion sur « SplashScreen : Wait and see »

  1. Merci à toi, j’avais un petit splashscreen avec une « bête » progress bar, résultat, j’ai une page de démarrage complètement animée, maintenant. Conseil (lu autre part), pour avoir une belle image au pixel prêt, tu fais tout en blend, puis dans l’emulateur, tu prends un snapshot de ton écran, que tu mets comme splascreenimage.jpg.

Les commentaires sont fermés.