This article is Day #3 in a series called 31 Days of Windows 8. Each of the articles in this series will be published for both HTML5/JS and XAML/C#. You can find additional resources, downloads, and source code on our website.
Today, we are going to talk about a small, but very important part of the application lifecycle: the splash screen. Some of you will see this as a silly topic at first, but it’s actually incredibly important from a user experience standpoint.
Let’s say, as an example, that your application connects to the internet to collect some data. Maybe you’re a weather app. Every time the user starts your app, they’re going to want up-to-the-second data. You know that this will generally take 2-3 seconds to grab the data, the appropriate images, and assemble them on your app’s page.
What we see happen in many apps is that the app loads empty, almost to a broken-looking page, only to get populated 2-3 seconds later. By utilizing the splash screen and its events, we can “extend” the splash screen experience, so that our users don’t see our application until we’re ready for that to happen. A couple of extra seconds looking at a splash screen is always preferable to opening a broken-looking app.
So, what we will be doing in this article is determining where the original splash screen image was positioned, and replacing it with our “placeholder” splash screen image until our application is appropriately populated.
Getting Started
If you recall from our article on Day #1, the splash screen image is always 620 x 300 pixels. For this example, we’re going to provide you with two versions of this image. The first is the original red one:
Additionally, we’ve created an identical version of the image in a purple color so that we can see the difference when they are swapped, while still being able to notice if the positioning of the text shifts at all.
Add these two images to your “Assets” folder in a new “blank” project. If you run that project after replacing the images, you should see the red image for a second or two before your applications loads to a dark screen.
Creating a Splash Screen Page
Our next step is to create a separate page to continue to the Splash Screen illusion. Add a new Blank page to your project:
We’ve named the page Splash.xaml, but you can name it whatever makes sense for your application. After adding our purple image to the page, here’s what the source looks like:
<Page
x:Class="Day3_SplashScreen.Splash"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Day3_SplashScreen"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="#464646">
<Image x:Name="SplashImage" Source="Assets/SplashScreenPlaceholder.png" Width="620" Height="300" />
</Grid>
</Page>
As you can see, very simple. Just added an Image to our page. The next step is to modify our App.xaml.cs file to direct the user to this page first.
Modifying our App.xaml.cs
Developers building simple applications may never even open this file, but this is where much of the magic happens. App.xaml.cs contains our startup methods and other system-level functionality, like managing state between app sessions. In this case, we’re looking for the OnLaunched() method. I’ve removed all of the extraneous comments that are there by default, but you’re specifically looking for the place where it’s trying to Navigate(typeof(MainPage), args.Arguments).
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new Frame();
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
if (!rootFrame.Navigate(typeof(Splash), args.Arguments))
{
throw new Exception("Failed to create initial page");
}
}
Window.Current.Activate();
}
By default, our application is trying to navigate to MainPage.xaml, and we want to change this. Replace the reference to MainPage with a reference to Splash, as I have done in my example above. This will take the user to our Splash.xaml page first, where we can do the loading we need to accomplish.
Go ahead and run your application. When we put our purple image in a grid, we destined it for a life of full centered-ness on the user’s screen. You should see that the purple box replaces the red box perfectly. Here’s a quick video to illustrate, in case you’re just reading along and not actually writing code (why aren’t you writing code?)
So are we done? Not even close. What we’ve got so far is the cheap, easy way to prolong the splash screen. There’s a far more complicated model to this if you’re interested.
The Harder, More Involved Way
Let’s say you’re looking for something more than just extending the length the splash screen shows. Perhaps you want to want to know WHEN the splash screen was dismissed, or the specific location that the splash screen image was displayed on the screen? You can do that, thanks to the SplashScreen object that the Windows.ApplicationModel.Activation namespace provides us.
First, let’s look at our App.xaml.cs file again. We’re going to change how we make the initial call to our Splash.xaml page by passing the SplashScreen object to our page constructor. To simplify, we have ripped all of the default code out of the OnLaunched method, and replaced it with this. We added comments to explain each line of the code:
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
//First we want to check to see if the application was already running.
if (args.PreviousExecutionState != ApplicationExecutionState.Running)
{
//If it wasn't, then we want to check to see if it was terminated the last time it was run,
//which we will pass on to our Splash page.
bool loadState = (args.PreviousExecutionState == ApplicationExecutionState.Terminated);
//Create a new Splash page object passing the SplashScreen object to the constructor.
Splash splashPage = new Splash(args.SplashScreen, loadState);
//Set our current app's content = the new Splash page.
Window.Current.Content = splashPage;
}
Window.Current.Activate();
}
Now that we have passed that information, we need to modify how our Splash.xaml.cs constructor is written so that we can retrieve those values when they arrive. Open up your Splash.xaml.cs file, and rewrite your public Splash() method to look like this:
public SplashScreen splashScreen;
public Rect splashImage;
public Splash(SplashScreen splashscreen, bool loadState)
{
this.InitializeComponent();
splashScreen = splashscreen;
splashImage = splashScreen.ImageLocation;
}
As you can see, since we changed how we call our Splash page in our App.xaml.cs file, we also need our constructor method to match that same signature, receiving a SplashScreen object and a boolean value. The LoadState value is passed to our page to let us know if we are loading from a previously terminated state or not. (Remember we set this value in the App.xaml.cs example above.)
Recognizing when the Splash Screen is dismissed
Our next step is to subscribe to the event handler for when the SplashScreen is dismissed. We do this like almost any other event handler. Add this line to the end of the new constructor method we created:
splashScreen.Dismissed += new TypedEventHandler<SplashScreen, Object>(splashScreen_Dismissed);
Since we have now defined a new event handler, we also need to create the method to catch that event, which we named splashScreen_dismissed. In this example, we have left it empty of any code, but this is the place you would add code that should be executed when the splash screen has been dismissed.
void splashScreen_Dismissed(SplashScreen sender, object args)
{
}
Determining location & size of the splash screen image
Finally, we need to determine where the splash screen was positioned on the screen. In this part of the example, we are going to use the location of the splash screen to determine where to place an advertisement image below it while the rest of our app loads.
First, here’s the advertisement image we’re using. (Feel free to use this in your apps.) 🙂
Add this to your project, and then update your Splash.xaml file to look like this:
<Canvas Background="#464646">
<Image x:Name="SplashScreenImage"
Source="Assets/SplashScreenPlaceholder.png"
Width="620"
Height="300"
Visibility="Collapsed"/>
<Image x:Name="AdvertisementImage"
Source="Assets/advertisementsample.png"
Width="620"
Height="100"
Visibility="Collapsed"/>
</Canvas>
As you can see in the XAML above, I’ve removed the Grid control and replaced it with a Canvas. This was really only to show that I’m not using any of the default centering properties of the Grid, and instead I’m going to have to be completely accurate in my image placement.
Head back over to your Splash.xaml.cs file, and add one more line to your constructor (the call to PositionAdvertisement), so that it looks like this final version:
public SplashScreen splashScreen;
public Rect splashImage;
public Splash(SplashScreen splashscreen, bool loadState)
{
this.InitializeComponent();
splashScreen = splashscreen;
splashImage = splashScreen.ImageLocation;
splashScreen.Dismissed += new TypedEventHandler<SplashScreen, Object>(splashScreen_Dismissed);
PositionAdvertisement();
}
void splashScreen_Dismissed(SplashScreen sender, object args)
{
}
Finally, we need to create the PositionAdvertisement method, and move our images to their appropriate locations before changing their Visibility properties to Visible. By accessing the X, Y, Height, and Width properties of the SplashScreen.ImageLocation object.
private void PositionAdvertisement()
{
SplashScreenImage.SetValue(Canvas.TopProperty, splashImage.Y);
SplashScreenImage.SetValue(Canvas.LeftProperty, splashImage.X);
SplashScreenImage.Height = splashImage.Height;
SplashScreenImage.Width = splashImage.Width;
SplashScreenImage.Visibility = Visibility.Visible;
AdvertisementImage.SetValue(Canvas.TopProperty, (splashImage.Y + splashImage.Height + 100));
AdvertisementImage.SetValue(Canvas.LeftProperty, splashImage.X);
AdvertisementImage.Visibility = Visibility.Visible;
}
As you can see, we’re positioning the SplashScreenImage to the same position as the default Splash Screen Image that is part of the application. Then, we set the advertisement to show up 100 pixels lower than the SplashScreenImage. So, your final Splash.xaml file should render to look like this (click to enlarge):
And that’s it!
Summary
In short, the splash screen can be your friend. It becomes a temporary veil to hide your application until it’s ready, as well as a place to host some advertisements in free applications. It’s a highly valuable piece of app real estate, and we definitely think it’s something you should consider taking advantage of in every application.
To download the entire sample solution from this article, you can download it here:
Tomorrow, we’re going to focus on some of the new common controls that are available to us in Windows 8 XAML development. We’ll look at things like the GridView, FlipView and more. But that’s tomorrow. See you then!
Leave a Reply