首先说一下初始屏幕设计的必要性。

  • 如果UWP应用的启动后需要加载的资源比较多,初始屏幕过后,有较长的等待时间,这时一个延长的初始屏幕可以很好的解决这个问题。
  • 系统默认的初始屏幕过于单调简单,一个更好的初始屏幕,会使app更加优秀。

初始屏幕的设置,在widows开发者文档中有详细介绍(延长显示初始屏幕的时间),但是按照这种方法做出来的有一个问题就是手机界面兼容性不好,会出现错位等问题,在博客园MS-UAP的“人群中看到你的第一眼-初始屏幕”中有解决办法。 完成后的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
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 Windows.UI.Core;
using Windows.UI.ViewManagement;
using PasswordTest.Helpers;
using Windows.UI;
using System.Reflection;
// https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板

namespace PasswordTest
{
///

/// 可用于自身或导航至 Frame 内部的空白页。
///

public sealed partial class SplashPage : Page
{
internal Rect splashImageRect; // 用来获取屏幕显示区域的大小
private SplashScreen splash; // Variable to hold the splash screen object.
internal bool dismissed = false; //追踪启动画面解除状态的变量。
internal Frame rootFrame;

// Define methods and constructor
public SplashPage(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)
{
// 注册一个事件处理程序,以便在启动屏幕被关闭时执行。
splash.Dismissed += new TypedEventHandler<SplashScreen, Object>(DismissedEventHandler);

// 检索启动屏幕图像的窗口坐标。
splashImageRect = splash.ImageLocation;
PositionImage();

// 如果使用,请包括一个定位进度控制的方法。
PositionRing();
}

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

void PositionImage()
{
// desktop
if (Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily.Equals("windows.desktop", StringComparison.CurrentCultureIgnoreCase))
{
extendedSplashImage.SetValue(Canvas.LeftProperty, splashImageRect.X);
extendedSplashImage.SetValue(Canvas.TopProperty, splashImageRect.Y);
extendedSplashImage.Height = splashImageRect.Height;
extendedSplashImage.Width = splashImageRect.Width;
}
// mobile
else if (Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily.Equals("windows.mobile", StringComparison.CurrentCultureIgnoreCase))
{
if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.UI.ViewManagement.StatusBar"))
{
// 需要引用Windows Mobile Extensions for the UWP
StatusBar sb = StatusBar.GetForCurrentView();
// 调整为透明,也可以用启动屏幕的背景色+不透明
sb.BackgroundOpacity = 0;
sb.ForegroundColor = Colors.Black;

// 撑满手机屏幕
Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().SetDesiredBoundsMode(Windows.UI.ViewManagement.ApplicationViewBoundsMode.UseCoreWindow);
}
// 获取一个值,该值表示每个视图(布局)像素的原始(物理)像素数。
double density = Windows.Graphics.Display.DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel;

extendedSplashImage.SetValue(Canvas.LeftProperty, splashImageRect.X / density);
extendedSplashImage.SetValue(Canvas.TopProperty, splashImageRect.Y / density);
extendedSplashImage.Height = splashImageRect.Height / density;
extendedSplashImage.Width = splashImageRect.Width / density;
}
}

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));
}
// 包括当系统从启动屏幕转换到扩展启动屏幕(应用程序的第一个视图)时要执行的代码。
async void DismissedEventHandler(SplashScreen sender, object e)
{
dismissed = true;
// 在这儿完成应用设置的操作

//在应用设置完成后,自动跳转到主页
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
//操作UI的代码
DismissExtendedSplash();
});
}

void DismissExtendedSplash()
{
// 导航到mainpage
rootFrame.Navigate(typeof(MainPage));
// 将frame放在当前窗口中
Window.Current.Content = rootFrame;
}

void ExtendedSplash\_OnResize(Object sender, WindowSizeChangedEventArgs e)
{
// 安全更新extended splash screen image的坐标.
//当用户调整窗口大小时,将执行此功能。
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();
}
}

//测试按钮
private void DismissSplashButton\_Click(object sender, RoutedEventArgs e)
{
DismissExtendedSplash();
}

//async void RestoreStateAsync(bool loadState)
//{
// if (loadState)
// {
// // 代码可以在这里加载你的应用程序的状态

// }
//}
}

}

但是,我按照这两篇帖子做后发现在初始界面加载完后需要导航到主页时,却发生异常。 提示跨线程操作UI,经过一番研究后,解决方法如下:

// 包括当系统从启动屏幕转换到扩展启动屏幕(应用程序的第一个视图)时要执行的代码。
async void DismissedEventHandler(SplashScreen sender, object e)
{
dismissed = true;
// 在这儿完成应用设置的操作

//在应用设置完成后,自动跳转到主页
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
//操作UI的代码
DismissExtendedSplash();
});
}

非UI线程访问UI参考这篇文章。点击链接 这样一个延长的初始屏幕就完成了,并且适配手机和pc,其他的就看自己发挥了。 还有一个问题是,在手机上ProgressRing不显示的问题,目前还没时间研究,等有结果了,再更新~ 更新:手机上不显示ProgressRing问题的原因找到了,是因为ProgressRing的位置有问题,就是它的坐标超出屏幕的显示范围了,所以看不到,具体解决方法及位置计算方法,详见UWP手机启动屏幕控件位置计算