概述
Toast Notification 在 UWP App 中有很重要的作用,能够很大程度上增强 App 和用户之间的沟通,比如运营推广活动、版本更新、提醒类任务提示等等。Toast Notification 可以通过图片、文字、按钮等创建可适配、可交互的通知。
我们在 About Windows 10 SDK Preview Build 17110 中对 Toast Notification 做了简单的介绍,本篇会从开发角度更更深入的解读。Toast Notification 主要分为网络内容通知和本地内容通知,本篇我们主要关注 Toast Notification 的以下新增功能的内容开发和显示,对于触发通知的源暂不细讲:
- 图片尺寸限制
- 进度条
- 新增的输入选项
开发过程
NuGet 安装
为了在 UWP 中实现 Toast Notification,我们需要引入一个 SDK:Microsoft.Toolkit.Uwp.Notifications ,通过 NuGet 在 Visual Studio 的Package Management 中安装:
Install-Package Microsoft.Toolkit.Uwp.Notifications -Version 2.2.0
基础实现
我们来实现一个样式比较基础的 Toast Notification,Toast 的内容主要包括以下几个部分:
- Launch — 定义一个参数,当用户点击 Toast 时传回到应用中,允许开发者深度链接到 Toast 显示的正确内容对应的应用页面内容中;
- Visual — Toast 的静态内容展示部分,包括文本和图像等;
- Actions — Toast 的可交互部分,包括可点击的按钮,文本输入等;
- Audio — 当 Toast 显示时,播放的音乐。
这里我们定义了 ToastContent 需要的基本内容:
string title = "Shaomeng sent you a picture"; string content = "Check this out!"; string image = "ms-appx:///assets/test.jpg"; string logo = "ms-appx:///assets/shaomeng.jpg"; // Construct the visuals of the toast ToastVisual visual = new ToastVisual() { BindingGeneric = new ToastBindingGeneric() { Children = { new AdaptiveText() { Text = title }, new AdaptiveText() { Text = content }, new AdaptiveImage() { Source = image } }, AppLogoOverride = new ToastGenericAppLogo() { Source = logo, HintCrop = ToastGenericAppLogoCrop.Circle } } }; // In a real app, these would be initialized with actual data int conversationId = 384928; // Construct the actions for the toast (inputs and buttons) ToastActionsCustom actions = new ToastActionsCustom() { Buttons = { new ToastButton("Like", new QueryString() { { "action", "like" }, { "conversationId", conversationId.ToString() } }.ToString()) { ActivationType = ToastActivationType.Background }, new ToastButton("View", new QueryString() { { "action", "viewImage" }, { "imageUrl", image } }.ToString()) } }; ToastAudio audio = new ToastAudio() { Src = new Uri("ms-appx:///assets/test.mp3", UriKind.RelativeOrAbsolute) };
使用上面的内容,定义一个 ToastContent,并把它显示出来:
ToastContent toastContent = new ToastContent() { Launch = "test string", Visual = visual, Actions = actions, Audio = audio, }; var toast = new ToastNotification(toastContent.GetXml()); ToastNotificationManager.CreateToastNotifier().Show(toast);
图片尺寸限制
Toast Notification 中允许使用的图片来源包括:http://,ms-appx:///,ms-appdata:///
对于网络图片,图片尺寸限制的单位是单个图片尺寸。16299 以后,normal connections 的限制是 3MB,metered connections 的限制是 1MB;而之前的限制统一是 200 KB。可以看到对网络图片的尺寸限制放宽了很多,很多高清晰度的图片也可以被使用。
如果你的图片超过了这个尺寸限制,或者下载过程中失败,超时,通知会正常被显示,不过图片部分会被放弃。
我们来做一下实际的验证,上面示例中我们使用了一张 buildcast 低分辨率 jpg 截图,只有 50KB 左右,如果把上面示例中的图片替换成 >3MB 的网络原始图片:
string image = "http://192.168.1.110/buildcast.png";
buildcast.png 的尺寸是 5.63MB,看看显示结果,确实放弃了图片,只显示了其他部分:
而如果使用同一张图片,但是把放到工程里呢:
string image = "ms-appx:///assets/buildcast.png";
结果就是,图片可以正常显示了。这也印证了上面的结论,图片尺寸限制只针对网络图片:
进度条
在某些场景,例如下载或其他过程进行时,需要在通知中显示进度条,让用户可以保持对进度的关注。进度条可以是不确定的或者确定的。
Toast Content 中,使用 AdaptiveProgressBar 类来实现进度条的显示和更新,如下图,它主要就以下几个属性:
- Title — 设置和显示进度条的标题,支持 DataBinding;
- Value — 设置和显示进度条当前进度,支持 DataBinding;默认值为 0.0,取值范围是 0.0 ~1.0;AdaptiveProgressBarValue.Indeterminate 代表不确定值,显示效果就是不断移动的三个点,表示某个不确定过程正在进行;new BindableProgressBarValue("myProgressValue") 为数值绑定的写法;
- ValueStringOverride — 设置和显示重写当前进度数值,支持 DataBinding;书写方式为 new BindableString("progressValueString"),
- Status — 设置和显示当前进度条状态,支持 DataBinding;如下图中的 Status 可能会有:downloading...,finished! 等;
接下来看一下代码示例:
- 我们给 ToastContent 设置了 Tag(或 Group),作为更新显示时的标识;
- AdaptiveProgressBar 中使用了 DataBinding 的方式来赋值,并在 Toast 第一次显示时,手动给它设置了初始值;
- 设置了 Toast 的 SequenceNumber,它是一个 uint 类型,在更新时,只有值大于前一次的值才会更新;所以如果你想每次都更新,初始值可以设置为 0;
// Define a tag (and optionally a group) to uniquely identify the notification, in order update the notification data later; string tag = "demo-filelist"; string group = "downloads"; // Construct the toast content with data bound fields ToastContent content = new ToastContent() { Visual = new ToastVisual() { BindingGeneric = new ToastBindingGeneric() { Children = { new AdaptiveText() { Text = "Downloading your demo files..." }, new AdaptiveProgressBar() { Title = "Demo Files", Value = new BindableProgressBarValue("progressValue"), ValueStringOverride = new BindableString("progressValueString"), Status = new BindableString("progressStatus") } } } } }; var toast = new ToastNotification(content.GetXml()); // Assign the tag and group toast.Tag = tag; toast.Group = group; //Assign initial NotificationData values toast.Data = new NotificationData(); toast.Data.Values["progressValue"] = "0.0"; toast.Data.Values["progressValueString"] = "0/10 files"; toast.Data.Values["progressStatus"] = "Downloading..."; // Provide sequence number to prevent out-of-order updates, or assign 0 to indicate "always update" toast.Data.SequenceNumber = 0; ToastNotificationManager.CreateToastNotifier().Show(toast);
下面是进度条更新的代码:
- 注意 Tag 和 Group 需要和创建 Toast 时保持一致,不然更新不会生效;
- SequenceNumber 设置的值需要比上一次的大,不然更新也不会生效;
- 我们进行了两次更新,一次是进行中,一次是已经完成;
// Construct a NotificationData object; string tag = "demo-filelist"; string group = "downloads"; // Create NotificationData and make sure the sequence number is incremented // since last update, or assign 0 for updating regardless of order var data = new NotificationData { SequenceNumber = seq_no }; // Assign new values if (seq_no == 1) { data.Values["progressValue"] = "0.7"; data.Values["progressValueString"] = "7/10 files"; } else if (seq_no == 2) { data.Values["progressValue"] = "1.0"; data.Values["progressValueString"] = "10/10 files"; data.Values["progressStatus"] = "Finished!"; } // Update the existing notification‘s data by using tag/group ToastNotificationManager.CreateToastNotifier().Update(data, tag, group);
来看看三个状态,初始值,更新1-进行中,更新2-已完成:
新增的输入选项
输入区域会出现在 Toast 中的 Actions 区域,也就是说只有 Toast 被展开的时候,输入区域才会显示出来。下面来看看几种常见的输入形式:
1. 快速回复输入
看一下输入部分的代码,添加了一个 ToastTextBox 来输入文字,添加了一个 ToastButton 来处理输入的文字,为了让按钮出现在文本框后面,ToastButton 的 TextBoxId 属性设置为 ToastTextBox 的 Id。而点击按钮后的操作,属于后台操作,不需要启动应用,也不需要关联协议启动其他应用。
// Construct the actions for the toast (inputs and buttons) ToastActionsCustom actions = new ToastActionsCustom() { Inputs = { new ToastTextBox("tbReply") { PlaceholderContent = "Type a reply" } }, Buttons = { new ToastButton("Reply", "action=reply&convId=9318") { ActivationType = ToastActivationType.Background, // To place the button next to the text box, // reference the text box‘s Id and provide an image TextBoxId = "tbReply", ImageUri = "Assets/if_paperfly_701491.png" } } };
运行效果如下图,折叠时文本框区域不显示,而输入文字点击按钮后,Toast 消失。
2. 带按钮栏输入
带按钮栏的输入相对更通用一些,输入框后面显示操作的若干按钮,点击每个按钮会有对应的操作
// Construct the actions for the toast (inputs and buttons) ToastActionsCustom actions = new ToastActionsCustom() { Inputs = { new ToastTextBox("tbReply") { PlaceholderContent = "Type a reply" } }, Buttons = { new ToastButton("Reply", "action=reply&threadId=9218") { ActivationType = ToastActivationType.Background }, new ToastButton("Video call", "action=videocall&threadId=9218") { ActivationType = ToastActivationType.Foreground } } };
3. 选择式输入
提供一个输入选项给用户,选择某个选项后,点击按钮会有对应的操作
Inputs = { new ToastSelectionBox("time") { DefaultSelectionBoxItemId = "lunch", Items = { new ToastSelectionBoxItem("breakfast", "Breakfast"), new ToastSelectionBoxItem("lunch", "Lunch"), new ToastSelectionBoxItem("dinner", "Dinner") } } },
4. 提醒式输入
基本构成和上面的选择式输入一致,只不过两个 Action 按钮是系统内置的按钮类型:推迟和取消
Inputs = { new ToastSelectionBox("snoozeTime") { DefaultSelectionBoxItemId = "15", Items = { new ToastSelectionBoxItem("5", "5 minutes"), new ToastSelectionBoxItem("15", "15 minutes"), new ToastSelectionBoxItem("60", "1 hour"), new ToastSelectionBoxItem("240", "4 hours"), new ToastSelectionBoxItem("1440", "1 day") } } }, Buttons = { new ToastButtonSnooze() { SelectionBoxId = "snoozeTime" }, new ToastButtonDismiss() }
主要看两个按钮:ToastButtonSnooze - 推迟按钮,根据上面 SelectionBox 选择的值,在指定时间后再次提醒;ToastButtonDismiss - 取消按钮,取消提醒;
到这里就把 Windows 10 SDK 17110 中针对 Toast Notification 新增的内容介绍完了,大家如果对 Toast Notification 感兴趣,可以做更深入的研究,相信一定会对你的 UWP App 有很大帮助。