﻿# WP7 修練 DAY 01：如何設計啟動畫面 (Splash screen)

每一個 Windows Phone 7 應用程式在啟動時多少會花上一些時間，在這個等待的時刻經常都會擺放一些啟動畫面 (Splash screen) 先來充充場面，以免載入時間過長而導致使用者不耐煩，而在這個啟動畫面裡你還能藉此廣告一下把公司的 LOGO、連絡方式、品牌資訊都顯示在這個頁面裡，當然時間不能太長、也不能太短，否則若這個啟動畫面跑得太快，那就沒有出現的必要性了，有時後這種必要的「慢」也是一種藝術。在第一篇修練文章中，我們就從最基本的建立專案開始講起，在開始之前，請先閱讀 [Windows Phone 7.5 (Mango) 開發學習資源整理](/post/2011/09/30/Windows-Phone-75-\(Mango\)-e9968be799bce5adb8e7bf92e8b387e6ba90e695b4e79086.aspx) 這篇文章設立基本的開發環境。

首先，我們先建立一個名為 **WP7XiuLianDay1\_SplashScreen** 的專案：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/ce5e46054d5197c02720-SNAGHTML16f9348f.png)

我們選用 ”芒果機” 的作業系統：Windows Phone OS 7.1

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/ff658b676a3b38982d0d-SNAGHTML16fa6188.png)

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/58be1533a31d60b81f6a-image_1190.png)

開啟專案後，直接新增一個 Windows Phone Portrait Page 頁面，並取名為 **SplashScreen.xaml**

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/593c32e16b633b1ac269-SNAGHTML16fd06ad.png)

新增完頁面後直接在 XAML 設計檢視按下 Ctrl + A 全選，並將所有頁面上的視覺元素刪除

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/bcf2fe71b66a448e351e-image_1191.png)

然後拉一個 Image 控制項進來

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/3a595d9d43fdd058c8cf-image_1192.png)

由於 Windows Phone 7 的螢幕大小目前都固定為 480 (寬) x 800 (高)，而且我們希望這個**啟動畫面**能夠佔滿整個畫面，所以我們必須調整 Image 控制項的屬性，這是透過拖曳的方式並不精準，直接修改屬性會比較快些。

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/f4f868da0c1d4bef3ab8-image_1193.png)

接著準備一張 480 x 800 的圖片（**注意**：不能使用 GIF 格式的圖檔），在此我的圖檔名為 SplashScreen.png 並用一個 Images 目錄來收納它。

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/406d4a5db9b35088e155-SNAGHTML1706994b.png)

然後再調整 Image 控制項的屬性，將圖片選進此控制項（意即設定 Source 屬性）

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/4e733b8b557cf5c19307-image_1194.png)

**補充說明**：我們也可以將 SplashScreen.png 圖檔的 **Build Action** **專案屬性**從 **Embedded Resource** 調整為 **Content**，此舉的主要目的是為了降低 WP7 組件的大小，以加快整體應用程式的載入速度。

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/3f0e055771f959f5d72e-image_1195.png)

不過修改了圖檔的專案屬性後，你的 Image 控制項的 Source 屬性也要跟著調整，且必須調整為**相對於專案根目錄**的**絕對路徑**，用文字描述比較難懂，看圖吧：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/fb3b156188395c17fb47-image_1196.png)

此時，我們有了兩個頁面，分別是預設首頁 MainPage.xaml 與另一個啟動頁面 SplashScreen.xaml，如果你此時想要預覽剛剛設計的這個頁面的話，可能必須寫一些程式碼，才能把預設首頁自動轉向到這裡，我們先用「偷懶」的作法來實做頁面自動轉向功能。

先開啟 MainPage.xaml 的程式碼：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/fce081894689d7055b26-image_1197.png)

然後加上該頁面的 Loaded 事件，並透過 NavigationService 實做轉向功能

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/20b3025a9db10fa91b28-image_1198.png)

請注意：這是為了測試方便才這樣寫的，此寫法有 2 個嚴重的缺點：一個是頁面會先讓你看到 MainPage.xaml 然後才會進入到 SplashScreen.xaml 頁面裡；另一個問題是進入該頁面後，若按下手機的**上一頁**按鈕，又會繼續跳到 SplashScreen.xaml 這頁，這並非常規的設計法則，小朋友請不要亂學。

這時按下 F5 就可以立即看到 SplashScreen.xaml 頁面的出現，不過如果你的眼睛夠尖的話，可能會發現這張圖其實並沒有顯示的很完整，雖然你的圖片是 480x800 的大小，不過呈現在模擬器或手機裡時，其高度會被自動往下擠了 32px 的高度，也就是被 **系統匣** (**System Tray**) 給佔用了！（如下圖示）

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/f4efdfe7d368389cc623-image_1199.png)

所以這張圖最下方的 32px 將會無法顯示在手機上，這一點其實在 XAML 設計檢視中也可以發現：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/a4a62719a2aade67d89f-image_1200.png)

這時你可以有兩種抉擇，第一種是跟限制妥協，另外準備一張 480 x 768 的圖片來當 Splash 畫面（註：我不建議直接把圖片進行縮放，這樣圖片可能會稍微變形或失真）。

另一種方法，是透過設定把系統匣整個隱藏起來，如此以來便可將 480x800 的圖片完整的呈現在手機上，你可以直接修改 XAML 檔的設定，如下圖示把 **shell:SystemTray.IsVisible** 屬性調整為 **False** 即可。

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/9dfbb7d99b3ff73ada1f-image_1209.png)

另一種透過程式控制的方法可以在 SplashScreen.xaml 頁面 Code Behind 程式裡的建構子的最後面加入以下程式碼，就可以做到這個效果：

先引用 Microsoft.Phone.Shell 命名空間

```
using Microsoft.Phone.Shell;
```

再到頁面的建構子輸入以下程式

```
this.SetValue(SystemTray.IsVisibleProperty, false);
```

  ![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/f8d34810e1429468e8af-image_1201.png)

這時你再執行一次，比較一下跟剛剛的圖片是不是不一樣了呢？

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/810c29397537b3f9cf9c-SNAGHTML1750155e.png)

目前我已經弄好一個 SplashScreen.xaml  頁面，當然，你也可以把這個頁面弄的很花俏，例如加上動畫或什麼的，但那不是本文章的重點，接下來就是本文的重頭戲，設計一個正規的應用程式**啟動畫面**。

我們之所以要做「啟動畫面」，目的可能有兩種：

1.  因為應用程式需要初始化的時間太長，所以需要先顯示一個簡單的等待頁面。而這也是 [Windows Phone Application Certification Requirements](http://msdn.microsoft.com/en-us/library/hh184843\(VS.92\).aspx) 的要求之一（請參見 [Technical Certification Requirements](http://msdn.microsoft.com/en-us/library/hh184840\(VS.92\).aspx) 頁面的 **5.2.1 Launch Time** 這一條規則），而這也是學會設計**啟動畫面**如此重要的原因之一。
2.  程式執行的太快，使用者沒有 feel，但要慢也要慢的優雅而從容。 XD

要讓 MainPage.xaml 正式開始執行之前，我們希望能先跳 SplashScreen.xaml 頁面出來，使用的技巧並不是先轉向到 SplashScreen.xaml 再轉回 MainPage.xaml 頁面，我們使用的技巧是透過一個 Popup 視窗擋住 MainPage.xaml 頁面，而這個 Popup 視窗裡就是包裹著 SplashScreen.xaml 頁面，以下是程式的寫法：

1\. 先在 MainPage.xaml.cs 最上方引用以下命名空間

```csharp
using System.Threading;
using System.Windows.Controls.Primitives;
using System.ComponentModel;
```

2\. 然後宣告兩個類別層級的私有變數、修正建構子、並加上一個背景處理的方法。這段程式碼主要是在頁面尚未載入完成之前就先顯示一個 Popup 視窗，並設定在 3 秒之後自動關閉（秒數你可以自行調整）：

```csharp
BackgroundWorker backroungWorker;
Popup myPopup;

public MainPage()
{
    InitializeComponent();

    myPopup = new Popup() { IsOpen = true, Child = new SplashScreen() };

    backroungWorker = new BackgroundWorker();
    RunBackgroundWorker();

}

private void RunBackgroundWorker()
{
    backroungWorker.DoWork += ((s, args) =>
    {
        Thread.Sleep(3000);
    });

    backroungWorker.RunWorkerCompleted += ((s, args) =>
    {
        this.Dispatcher.BeginInvoke(() =>
        {
            this.myPopup.IsOpen = false;
        });
    });

    backroungWorker.RunWorkerAsync();
}
```

這時按下 F5 執行你會看到 SplashScreen.xaml 顯示 3 秒鐘後會自動關閉，但有趣的是，我們剛剛第一次顯示這個頁面時，這張 480x800 的圖的最下方被截掉了 32px 的空間，而這次透過 Popup 的方式卻是最上方的 32px 被截掉！（我覺得我可能是被客戶磨到成精了，盡是注意這些雞毛蒜皮的事 XD）

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/c122e38f9e169196a03c-SNAGHTML177a6208.png)

我們一樣套用剛剛學過的 Hack 技法，改寫這段程式碼，當我們顯示 Popup 頁面時 (SplashScreen.xaml) 關閉系統匣顯示，當關閉 Popup 頁面時再重新顯示系統匣，完整程式碼如下：

```csharp
using System;
using Microsoft.Phone.Controls;

using System.Threading;
using System.Windows.Controls.Primitives;
using System.ComponentModel;
using Microsoft.Phone.Shell;

namespace WP7XiuLianDay1_SplashScreen
{
    public partial class MainPage : PhoneApplicationPage
    {
        BackgroundWorker backroungWorker;
        Popup myPopup;

        public MainPage()
        {
            InitializeComponent();

            myPopup = new Popup() { IsOpen = true, Child = new SplashScreen() };
            backroungWorker = new BackgroundWorker();
            RunBackgroundWorker();

            this.SetValue(SystemTray.IsVisibleProperty, false);
        }

        private void RunBackgroundWorker()
        {
            backroungWorker.DoWork += ((s, args) =>
            {
                Thread.Sleep(3000);
            });

            backroungWorker.RunWorkerCompleted += ((s, args) =>
            {
                this.Dispatcher.BeginInvoke(() =>
                {
                    this.myPopup.IsOpen = false;
                    this.SetValue(SystemTray.IsVisibleProperty, true);
                }
            );
            });
            backroungWorker.RunWorkerAsync();
        }
    }
}
```

**今日修煉總結**

今天我學到了如何有時後 GUI 介面不見得最方便，有時後手動修改 XAML 或調整屬性值比用圖形介面來拖曳來的方便。WP7 並不支援 GIF 圖檔（這是有專利的圖形格式），使用時應該避免使用 GIF 圖檔，否則看不到圖片你還會覺得是 WP7 的 Bug。也學到可以將 SplashScreen.png 圖檔的 Build Action 專案屬性從 Embedded Resource 調整為 Content，這樣可以降低 WP7 組件 (assembly) 的大小，以加快整體應用程式的載入速度。

除此之外，還學到了 WP7 手機一定會有個 **系統匣** (**System Tray**) 顯示在頁面最上方，要完整顯示 480x800 的畫面則必須透過一些 Hack 技巧才能實現此功能。最後學到了如何正確的使用 Popup 類別來顯示**啟動畫面**，並透過 BackgroundWorker 的背景作業來設定固定時間後自動關閉**啟動畫面**。

**相關連結**

-   [Splash screen - Wikipedia, the free encyclopedia](http://en.wikipedia.org/wiki/Splash_screen)
-   [Application Certification Requirements for Windows Phone](http://msdn.microsoft.com/en-us/library/hh184843\(VS.92\).aspx)
-   [All about Splash Screens in WP7 – Creating animated Splash Screen](http://www.windowsphonegeek.com/articles/All-about-Splash-Screens-in-WP7-ndash-Creating-animated-Splash-Screen)
-   [Performance Considerations in Applications for Windows Phone](http://msdn.microsoft.com/zh-cn/library/ff967560.aspx)
-   [WP7开发解惑（1）：BuildAction之Content与Resource](http://mol365.net/post/WP7e5bc80e58f91e8a7a3e68391efbc881efbc89efbc9aBuildActione4b98bContente4b88eResource.aspx)
-   [點部落 Windows Phone 7 修練大會](https://dotblogs.com.tw/)
