共用方式為


顯示啟動畫面以延長時間

透過為您的應用程式建立延長的啟動畫面,可以延長啟動畫面的顯示時間。 此延伸畫面會模仿啟動您的應用程式時所顯示的啟動顯示畫面,但可以自定義。 無論您是要顯示即時載入資訊,或者只是讓您的 app 具有額外的時間來準備其初始 UI,擴展啟動畫面可讓您設定啟動時的體驗。

備註

本主題中的「延長啟動顯示畫面」一詞是指會在螢幕上顯示較長時間的啟動顯示畫面。 這並不意味著從 SplashScreen 類別衍生的子類別。

重要 API

本主題中會使用下列 API:

預設啟動顯示畫面建議

請遵循下列建議,確定您的擴充啟動顯示畫面正確模擬預設啟動顯示畫面:

  • 您的延伸啟動顯示畫面頁面應該使用 620 x 300 像素的影像,與應用程式指令清單中針對啟動顯示畫面指定的影像一致(您的應用程式啟動顯示畫面影像)。 在 Microsoft Visual Studio 中,啟動顯示畫面的設定會儲存在應用程式套件宣告(Package.appxmanifest 檔案)的 [Visual Assets] 索引標籤下的 [啟動顯示畫面] 區段。
  • 您的延伸啟動顯示畫面應該使用與應用程式指令清單中針對啟動顯示畫面指定的背景色彩一致的背景色彩(您的應用程式啟動顯示畫面背景)。
  • 您的程式代碼應該使用 SplashScreen 類別,將 app 的啟動顯示畫面影像放置在與預設啟動顯示畫面相同的螢幕座標上。
  • 您的程式碼應使用 SplashScreen 類別來回應視窗大小調整事件(例如,當螢幕旋轉或您的應用程式移到螢幕上的其他應用程式旁邊時),以重新排列延伸啟動畫面上的項目。

使用下列步驟來建立延伸啟動顯示畫面,以有效模擬預設啟動顯示畫面。

空白頁面 專案新增至現有的應用程式

本主題假設您想要使用 C#、Visual Basic 或 C++,將延伸啟動顯示畫面新增至現有的通用 Windows 平臺 (UWP) 應用程式專案。

  • 在 Visual Studio 中開啟您的應用程式。
  • 從選單列開啟 Project,然後點擊 新增項目。 [新增項目 ] 對話框將會顯示
  • 在此對話框中,將新的 空白頁面 新增至您的應用程式。 本主題將擴充的啟動畫面頁面命名為「ExtendedSplash」。

新增 空白頁面 項目會產生兩個檔案,一個用於標記(ExtendedSplash.xaml),另一個用於程式代碼(ExtendedSplash.xaml.cs)。

擴充啟動顯示畫面的基本 XAML

請遵循下列步驟,將影像和進度控制項新增至延伸啟動畫面。

在您的 ExtendedSplash.xaml 檔案中:

  • 變更預設 Grid 元素的 Background 屬性,以符合您在 app 指令清單中為 app 啟動顯示畫面設定的背景色彩(在 Package.appxmanifest 檔案的 Visual Assets 區段)。 默認啟動顯示畫面色彩為淺灰色(十六進位值 #464646)。 請注意,當您建立新的 空白頁面時,預設會提供此 Grid 元素。 您不需要使用 Grid;這只是一個方便建置擴展啟動畫面的基礎。
  • Canvas 元素新增至 Grid。 您將使用此 Canvas 來放置延伸啟動畫面圖像。
  • Image 元素新增至 Canvas。 為延伸啟動顯示畫面使用與預設啟動顯示畫面相同的 620 x 300 像素影像。
  • (選擇性)新增進度控制件,以向使用者顯示程式正在載入。 本主題會新增 ProgressRing,而不是使用可確定或不可確定的 ProgressBar

以下範例示範具有這些新增和變更的 格狀

    <Grid Background="#464646">
        <Canvas>
            <Image x:Name="extendedSplashImage" Source="Assets/SplashScreen.png"/>
            <ProgressRing Name="splashProgressRing" IsActive="True" Width="20" HorizontalAlignment="Center"></ProgressRing>
        </Canvas>
    </Grid>

備註

本範例會將 ProgressRing 的寬度設定為 20 像素。 您可以手動將其寬度設定為適用於您 app 的值,不過,控件不會以小於 20 像素的寬度呈現。

擴充啟動顯示畫面類別的基本程序代碼

每當視窗大小(僅限 Windows)或方向發生變更時,延伸啟動畫面應作出反應。 您必須更新您使用的影像位置,以便不論視窗如何變更,您的延長啟動顯示畫面看起來都不錯。

使用這些步驟來定義方法,以正確顯示您的擴充啟動顯示畫面。

  1. 新增必要的命名空間

    您必須將下列命名空間新增至 ExtendedSplash.xaml.cs,以存取 SplashScreen 類別、Rect 結構,以及 Window.SizeChanged 事件。

    using Windows.ApplicationModel.Activation;
    using Windows.Foundation;
    using Windows.UI.Core;
    
  2. 建立部分類別並宣告類別變數

    將以下程式碼加入 ExtendedSplash.xaml.cs 中,以建立部分類別來代表延伸啟動顯示畫面。

    partial class ExtendedSplash : Page
    {
        internal Rect splashImageRect; // Rect to store splash screen image coordinates.
        private SplashScreen splash; // Variable to hold the splash screen object.
        internal bool dismissed = false; // Variable to track splash screen dismissal status.
        internal Frame rootFrame;
    
       // Define methods and constructor
    }
    

    這些類別變數是由數種方法使用。 splashImageRect 變數會儲存系統顯示應用程式的啟動畫面圖像的座標。 splash 變數會儲存 SplashScreen 物件,而 dismissed 變數會追蹤系統顯示的啟動畫面是否已被關閉。

  3. 定義類別的建構函式,以正確定位影像

    下列程式代碼會定義擴充啟動顯示畫面類別的建構函式,該類別會接聽視窗重設大小事件、將影像和 (選擇性) 進度控件放置在延伸啟動顯示畫面上、建立流覽框架,以及呼叫異步方法來還原已儲存的會話狀態。

    public ExtendedSplash(SplashScreen splashscreen, bool loadState)
    {
        InitializeComponent();
    
        // Listen for window resize events to reposition the extended splash screen image accordingly.
        // This ensures that the extended splash screen formats properly in response to window resizing.
        Window.Current.SizeChanged += new WindowSizeChangedEventHandler(ExtendedSplash_OnResize);
    
        splash = splashscreen;
        if (splash != null)
        {
            // Register an event handler to be executed when the splash screen has been dismissed.
            splash.Dismissed += new TypedEventHandler<SplashScreen, Object>(DismissedEventHandler);
    
            // Retrieve the window coordinates of the splash screen image.
            splashImageRect = splash.ImageLocation;
            PositionImage();
    
            // If applicable, include a method for positioning a progress control.
            PositionRing();
        }
    
        // Create a Frame to act as the navigation context
        rootFrame = new Frame();            
    }
    

    請務必在您的類別建構函式中註冊 Window.SizeChanged 處理程式(ExtendedSplash_OnResize 範例中的)以確保您的應用程式能在延伸啟動顯示畫面中正確定位影像。

  4. 定義類別方法,將影像定位在您的延伸啟動畫面

    此程式代碼示範如何使用 splashImageRect 類別變數,在延伸啟動顯示畫面頁面上放置影像。

    void PositionImage()
    {
        extendedSplashImage.SetValue(Canvas.LeftProperty, splashImageRect.X);
        extendedSplashImage.SetValue(Canvas.TopProperty, splashImageRect.Y);
        extendedSplashImage.Height = splashImageRect.Height;
        extendedSplashImage.Width = splashImageRect.Width;
    }
    
  5. (選擇性) 定義一個類別中的方法,以將進度控制項置於延伸的啟動畫面

    如果您選擇將 ProgressRing 新增至延伸啟動畫面,請將它放在相對於啟動畫面的圖片位置。 新增下列程式代碼以ExtendedSplash.xaml.cs將 ProgressRing 置中, 影像下方 32 圖元。

    void PositionRing()
    {
        splashProgressRing.SetValue(Canvas.LeftProperty, splashImageRect.X + (splashImageRect.Width*0.5) - (splashProgressRing.Width*0.5));
        splashProgressRing.SetValue(Canvas.TopProperty, (splashImageRect.Y + splashImageRect.Height + splashImageRect.Height*0.1));
    }
    
  6. 在類別內,定義 Dismissed 事件 的處理程式

    在 ExtendedSplash.xaml.cs 中,以回應 SplashScreen.Dismissed 事件的發生,將 dismissed 類別變數設定為 true。 如果您的應用程式有設定作業,請將它們新增至此事件處理程式。

    // Include code to be executed when the system has transitioned from the splash screen to the extended splash screen (application's first view).
    void DismissedEventHandler(SplashScreen sender, object e)
    {
        dismissed = true;
    
        // Complete app setup operations here...
    }
    

    完成應用程式設定之後,請離開延伸啟動顯示畫面。 下列程式代碼會定義名為 DismissExtendedSplash 的方法,該方法會巡覽至應用程式 MainPage.xaml 檔案中定義的 MainPage

    async void DismissExtendedSplash()
      {
         await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() =>            {
              rootFrame = new Frame();
              rootFrame.Content = new MainPage(); Window.Current.Content = rootFrame;
            });
      }
    
  7. 類別內部,定義 Window.SizeChanged 事件的處理程式

    準備您的延伸啟動顯示畫面,以在使用者調整視窗大小時重新調整其元素的位置。 當 Window.SizeChanged 事件發生時,此程式碼會擷取新座標並重新定位影像以回應事件。 如果您已將進度控件新增至延伸啟動顯示畫面,也請將它重新置放在此事件處理程式內。

    void ExtendedSplash_OnResize(Object sender, WindowSizeChangedEventArgs e)
    {
        // Safely update the extended splash screen image coordinates. This function will be executed when a user resizes the window.
        if (splash != null)
        {
            // Update the coordinates of the splash screen image.
            splashImageRect = splash.ImageLocation;
            PositionImage();
    
            // If applicable, include a method for positioning a progress control.
            // PositionRing();
        }
    }
    

    備註

     在您嘗試取得影像位置之前,請確定類別變數 (splash) 包含有效的 SplashScreen 物件,如範例所示。

     

  8. (選擇性)新增類方法以還原已儲存的會話狀態

    您在步驟 4:修改啟動啟用處理程式 中新增至 OnLaunched 方法的程式碼,會使應用程式在啟動時顯示延伸的起始畫面。 若要合併擴充啟動顯示畫面類別中與應用程式啟動相關的所有方法,您可以考慮將方法新增至ExtendedSplash.xaml.cs檔案,以還原應用程式的狀態。

    void RestoreState(bool loadState)
    {
        if (loadState)
        {
             // code to load your app's state here
        }
    }
    

    當您在 App.xaml.cs 中修改啟動啟用處理程式時,當應用程式的前一個 loadstate終止時,您會將 設定為 true。 如果是,RestoreState 方法會將應用程式還原為其先前的狀態。 如需應用程式啟動、暫停和終止的概觀,請參閱 應用程式生命週期

修改啟動啟用處理程式

啟動您的應用程式時,系統會將啟動顯示畫面資訊傳遞至應用程式的啟動啟用事件處理程式。 您可以使用這項資訊,在延伸啟動顯示畫面頁面上正確定位影像。 您可以從傳遞至您應用程式的 OnLaunched 處理函式的啟動事件的參數中取得此啟動畫面資訊(請參閱下列程式碼中的 args 變數)。

如果您尚未為應用程式覆寫 OnLaunched 處理常式,請參閱 應用程式生命週期 以瞭解如何處理啟用事件。

在 App.xaml.cs 裡,新增以下程式碼來建立並顯示擴展啟動畫面。

protected override void OnLaunched(LaunchActivatedEventArgs args)
{
    if (args.PreviousExecutionState != ApplicationExecutionState.Running)
    {
        bool loadState = (args.PreviousExecutionState == ApplicationExecutionState.Terminated);
        ExtendedSplash extendedSplash = new ExtendedSplash(args.SplashScreen, loadState);
        Window.Current.Content = extendedSplash;
    }

    Window.Current.Activate();
}

完整程式碼

下列程式代碼與先前步驟中顯示的代碼段稍有不同。

  • ExtendedSplash.xaml 包含 DismissSplash 按鈕。 按下此按鈕時,事件處理程式 DismissSplashButton_Click會呼叫 DismissExtendedSplash 方法。 在您的應用程式中,當您的應用程式完成載入資源或初始化其 UI 時,請呼叫 DismissExtendedSplash
  • 此應用程式也會使用 UWP 應用程式專案範本,此範本會使用 Frame 導覽。 因此,在App.xaml.cs中,啟動啟用處理程式(OnLaunched) 會定義 rootFrame,並用它來設定應用程式視窗的內容。

ExtendedSplash.xaml

此範例包含 DismissSplash 按鈕,因為它沒有要載入的應用程式資源。 在您的應用程式中,當完成載入資源或準備其初始介面時,自動關閉擴展的啟動畫面。

<Page
    x:Class="SplashScreenExample.ExtendedSplash"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:SplashScreenExample"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="#464646">
        <Canvas>
            <Image x:Name="extendedSplashImage" Source="Assets/SplashScreen.png"/>
            <ProgressRing Name="splashProgressRing" IsActive="True" Width="20" HorizontalAlignment="Center"/>
        </Canvas>
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Bottom">
            <Button x:Name="DismissSplash" Content="Dismiss extended splash screen" HorizontalAlignment="Center" Click="DismissSplashButton_Click" />
        </StackPanel>
    </Grid>
</Page>

ExtendedSplash.xaml.cs

請注意,會從 DismissExtendedSplash 按鈕的 click 事件處理程式呼叫 DismissSplash 方法。 在您的應用程式中,您不需要 DismissSplash 按鈕。 相反地,當您的應用程式完成載入資源並想要流覽至其主頁面時,請呼叫 DismissExtendedSplash

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
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.ApplicationModel.Activation;
using SplashScreenExample.Common;
using Windows.UI.Core;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/p/?LinkID=234238

namespace SplashScreenExample
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    partial class ExtendedSplash : Page
    {
        internal Rect splashImageRect; // Rect to store splash screen image coordinates.
        private SplashScreen splash; // Variable to hold the splash screen object.
        internal bool dismissed = false; // Variable to track splash screen dismissal status.
        internal Frame rootFrame;

        public ExtendedSplash(SplashScreen splashscreen, bool loadState)
        {
            InitializeComponent();

            // Listen for window resize events to reposition the extended splash screen image accordingly.
            // This is important to ensure that the extended splash screen is formatted properly in response to snapping, unsnapping, rotation, etc...
            Window.Current.SizeChanged += new WindowSizeChangedEventHandler(ExtendedSplash_OnResize);

            splash = splashscreen;

            if (splash != null)
            {
                // Register an event handler to be executed when the splash screen has been dismissed.
                splash.Dismissed += new TypedEventHandler<SplashScreen, Object>(DismissedEventHandler);

                // Retrieve the window coordinates of the splash screen image.
                splashImageRect = splash.ImageLocation;
                PositionImage();

                // Optional: Add a progress ring to your splash screen to show users that content is loading
                PositionRing();
            }

            // Create a Frame to act as the navigation context
            rootFrame = new Frame();

            // Restore the saved session state if necessary
            RestoreState(loadState);
        }

        void RestoreState(bool loadState)
        {
            if (loadState)
            {
                // TODO: write code to load state
            }
        }

        // Position the extended splash screen image in the same location as the system splash screen image.
        void PositionImage()
        {
            extendedSplashImage.SetValue(Canvas.LeftProperty, splashImageRect.X);
            extendedSplashImage.SetValue(Canvas.TopProperty, splashImageRect.Y);
            extendedSplashImage.Height = splashImageRect.Height;
            extendedSplashImage.Width = splashImageRect.Width;

        }

        void PositionRing()
        {
            splashProgressRing.SetValue(Canvas.LeftProperty, splashImageRect.X + (splashImageRect.Width*0.5) - (splashProgressRing.Width*0.5));
            splashProgressRing.SetValue(Canvas.TopProperty, (splashImageRect.Y + splashImageRect.Height + splashImageRect.Height*0.1));
        }

        void ExtendedSplash_OnResize(Object sender, WindowSizeChangedEventArgs e)
        {
            // Safely update the extended splash screen image coordinates. This function will be fired in response to snapping, unsnapping, rotation, etc...
            if (splash != null)
            {
                // Update the coordinates of the splash screen image.
                splashImageRect = splash.ImageLocation;
                PositionImage();
                PositionRing();
            }
        }

        // Include code to be executed when the system has transitioned from the splash screen to the extended splash screen (application's first view).
        void DismissedEventHandler(SplashScreen sender, object e)
        {
            dismissed = true;

            // Complete app setup operations here...
        }

        void DismissExtendedSplash()
        {
            // Navigate to mainpage
            rootFrame.Navigate(typeof(MainPage));
            // Place the frame in the current Window
            Window.Current.Content = rootFrame;
        }

        void DismissSplashButton_Click(object sender, RoutedEventArgs e)
        {
            DismissExtendedSplash();
        }
    }
}

App.xaml.cs

此專案是使用 Visual Studio 中的 UWP 應用程式 空白應用程式 (XAML) 項目範本所建立。 這些 OnNavigationFailedOnSuspending 事件處理程式會自動產生,不需要更改來實作延伸啟動顯示畫面。 本主題只會修改 OnLaunched

如果您未針對應用程式使用專案範本,請參閱步驟 4:修改啟動啟用處理程式,以取得未使用 OnLaunched 導覽的已修改 範例。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
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;

// The Blank Application template is documented at https://go.microsoft.com/fwlink/p/?LinkID=234227

namespace SplashScreenExample
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default Application class.
    /// </summary>
    sealed partial class App : Application
    {
        /// <summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            Microsoft.ApplicationInsights.WindowsAppInitializer.InitializeAsync(
            Microsoft.ApplicationInsights.WindowsCollectors.Metadata |
            Microsoft.ApplicationInsights.WindowsCollectors.Session);
            this.InitializeComponent();
            this.Suspending += OnSuspending;
        }

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used such as when the application is launched to open a specific file.
        /// </summary>
        /// <param name="e">Details about the launch request and process.</param>
        protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
#if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = true;
            }
#endif

            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();
                // Set the default language
                rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];

                rootFrame.NavigationFailed += OnNavigationFailed;

                //  Display an extended splash screen if app was not previously running.
                if (e.PreviousExecutionState != ApplicationExecutionState.Running)
                {
                    bool loadState = (e.PreviousExecutionState == ApplicationExecutionState.Terminated);
                    ExtendedSplash extendedSplash = new ExtendedSplash(e.SplashScreen, loadState);
                    rootFrame.Content = extendedSplash;
                    Window.Current.Content = rootFrame;
                }
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                rootFrame.Navigate(typeof(MainPage), e.Arguments);
            }
            // Ensure the current window is active
            Window.Current.Activate();
        }

        /// <summary>
        /// Invoked when Navigation to a certain page fails
        /// </summary>
        /// <param name="sender">The Frame which failed navigation</param>
        /// <param name="e">Details about the navigation failure</param>
        void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
        }

        /// <summary>
        /// Invoked when application execution is being suspended.  Application state is saved
        /// without knowing whether the application will be terminated or resumed with the contents
        /// of memory still intact.
        /// </summary>
        /// <param name="sender">The source of the suspend request.</param>
        /// <param name="e">Details about the suspend request.</param>
        private void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            // TODO: Save application state and stop any background activity
            deferral.Complete();
        }
    }
}

參考