Более продолжительное отображение экрана-заставки

Увеличьте длительность отображения экрана-заставки, создав и использовав расширенный экран-заставку для приложения. Этот расширенный экран имитирует экран-заставку, отображаемый при запуске приложения, но его можно настраивать. Если вы хотите показывать информацию о загрузке в реальном времени или дать приложению дополнительное время на подготовку начального пользовательского интерфейса, расширенный экран-заставка позволит определить взаимодействие с пользователем при запуске.

Примечание

Фраза "расширенный экран-заставка" в этом разделе относится к экрану-заставке, который остается на экране в течение длительного периода времени. Он не представляет подкласс, производный от класса SplashScreen.

Важные API

В этом разделе используются следующие API:

Рекомендации по экранам-заставкам по умолчанию

Убедитесь, что ваш расширенный экран-заставка точно имитирует экран-заставку, отображаемый по умолчанию. Для этого следуйте приведенным ниже рекомендациям.

  • Страница расширенного экрана-заставки должна использовать изображение размером 620 x 300 пикселей, соответствующее изображению, которое указано для экрана-заставки в манифесте приложения (изображение экрана-заставки вашего приложения). В Microsoft Visual Studio параметры экрана-заставки хранятся в разделе Экран-заставка вкладки Визуальные ресурсы манифеста приложения (файл Package.appxmanifest).
  • Расширенный экран-заставка должен использовать цвет фона, соответствующий цвету фона, который указан для экрана-заставки в манифесте приложения (фон экрана-заставки вашего приложения).
  • Чтобы расположить изображение расширенного экрана-заставки вашего приложения в тех экранных координатах, в которых располагается экран-заставка, отображаемый по умолчанию, в коде необходимо использовать класс SplashScreen.
  • Код должен реагировать на события изменения размера окна (например, при повороте экрана или при размещении вашего приложения рядом с другим приложением, открытым на экране), изменяя положение элементов на расширенном экране-заставке при помощи класса SplashScreen.

Чтобы создать расширенный экран-заставку, имитирующий экран-заставку, который отображается по умолчанию, используйте процедуру, описанную ниже.

Добавление элемента Пустая страница в существующее приложение

В этой статье подразумевается, что вы хотите добавить расширенный экран-заставку в существующий проект приложения универсальной платформы Windows (UWP) на C#, Visual Basic или C++.

  • Откройте приложение в Visual Studio.
  • Откройте пункт Проект в строке меню и нажмите кнопку Добавить новый элемент. Откроется диалоговое окно Добавление нового элемента.
  • В этом диалоговом окне добавьте новую пустую страницу в приложение. В этом разделе страница расширенного экрана-заставки называется ExtendedSplash.

При добавлении элемента пустая страница создаются два файла: один для разметки (ExtendedSplash.xaml) и второй для кода (ExtendedSplash.xaml.cs).

Базовый код XAML для расширенного экрана-заставки

Выполните эти действия, чтобы добавить изображение и элемент управления «Ход выполнения» на расширенный экран-заставку.

В файле ExtendedSplash.xaml:

  • Измените свойство Background элемента по умолчанию Grid в соответствии с цветом фона, настроенным для экрана-заставки вашего приложения в его манифесте (в разделе Визуальные активы файла Package.appxmanifest). Цвет экрана-заставки по умолчанию — светло-серый (шестнадцатеричное значение #464646). Обратите внимание, что этот элемент Grid предоставляется по умолчанию при создании новой пустой страницы. Не нужно обязательно использовать Grid, — это просто удобная основа для создания расширенного экрана-заставки.
  • Добавьте элемент Canvas в Grid. Canvas используется для размещения изображения расширенного экрана-заставки.
  • Добавьте элемент Image в Canvas. Используйте то же изображение 620 x 300 пикселей для расширенного экрана-заставки, которое вы выбрали для экрана-заставки по умолчанию.
  • (Необязательно) Добавьте элемент управления «Ход выполнения», который покажет пользователям, что ваше приложение загружается. В этом разделе добавляется элемент ProgressRing вместо определенного или неопределенного элемента ProgressBar.

В следующем примере показан элемент Grid с этими дополнениями и изменениями.

    <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 пикселям. Можно вручную задать для ширины значение, подходящее для вашего приложения, но элемент управления не будет выполнять отрисовку при ширине меньше 20 пикселей.

Базовый код для класса расширенного экрана-заставки

Расширенный экран-заставка должен реагировать на любые изменения размера (только Windows) или ориентации окна. Необходимо обновлять положение используемого изображения таким образом, чтобы расширенный экран-заставка смотрелся хорошо независимо от изменения размера окна.

Используйте эту процедуру, чтобы определить методы правильного отображения расширенного экрана-заставки.

  1. Добавление необходимых пространств имен

    Чтобы получить доступ к классу SplashScreen, структуре Rect и событиям Window.SizeChanged, необходимо добавить следующие пространства имен в файл ExtendedSplash.xaml.cs.

    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, определенную в файле MainPage.xaml приложения.

    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. (Необязательно) Добавьте метода класса для восстановления сохраненного состояния сеанса

    В результате выполнения кода, добавленного в метод OnLaunched в разделе «Шаг 4. Изменение обработчика события активации запуска», при запуске приложение отображает расширенный экран-заставку. Чтобы объединить все методы, связанные с запуском приложения в классе расширенного экрана-заставки, можно добавить метод в файл ExtendedSplash.xaml.cs для восстановления состояния приложения.

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

    При изменении обработчика активации запуска в файле App.xaml.cs также задайте для loadstate значение true, если предыдущее состояние ApplicationExecutionState приложения было Terminated. В этом случае метод 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. В приложении вызовите 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 метод вызывается из обработчика событий щелчка для кнопки 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

Этот проект был создан с помощью шаблона проекта пустого приложения UWP (XAML) в Visual Studio. Оба обработчика событий, OnNavigationFailed и OnSuspending, создаются автоматически, и их не нужно менять для реализации расширенного экрана-заставки. В этом разделе меняется только OnLaunched.

Если вы не использовали шаблон проекта для своего приложения, посмотрите в разделе «Шаг 4. Изменение обработчика активации запуска» пример измененного обработчика OnLaunched, который не использует навигацию Frame.

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();
        }
    }
}

Справочные материалы