Windows 10 UWP 6 of N : New Tile and Toast Notification

  • 1307
  • 0
  • UAP
  • 2021-04-30

Windows 10 UWP 6 of N : New Tile and Toast Notification

從Windows Phone 7.0 開始Windows就採用動態磚為App的外貌一直到現在Universal Windows App on Windows 10(以下皆簡稱UWP)都還是採用相同基礎的視覺體驗。

而User最直接看到的視覺體驗就是動態磚(Tile)、通知(Toast)的操作方式,問題是在Windows 和Windows Phone 的磚塊顯示依然有所區別,到了UWP才針對這部分有做了統一性的設計(當然還是有些許的差異~)

之前在Windows 8都是採用5px為基礎視覺單位值、在Windows 10則是採用4epx為單位。動態磚也分成四種大小

  • Small 1x1
  • Medium 2x2
  • Wide 4x2
  • Large 4x4 ( Desktop only. )

現在在Notification的樣板做了統一,所以出現了Adaptive Tile Template!如下的XML就是簡略的格式的Adaptive tile XML schema

  <visual>

    <binding template="TileMedium">
      ...
    </binding>

    <binding template="TileWide">
      <text hint-style="subtitle">Jennifer Parker</text>
      <text hint-style="captionSubtle">Photos from our trip</text>
      <text hint-style="captionSubtle">Check out these awesome photos I took while in New Zealand!</text>
    </binding>

    <binding template="TileLarge">
      ...
    </binding>

  </visual>
</tile>

主要是有個tile的Root接著是visual,tile本身沒有其他Attribute。

  version? = integer
  lang? = string
  baseUri? = anyURI
  branding? = "none" | "logo" | "name" | "nameAndLogo"
  addImageQuery? = boolean
  contentId? = string
  displayName? = string >
    
  <!-- Child elements -->
  binding+

</visual>

以上是visual的attribute

  template = tileTemplateNameV3
  fallback? = tileTemplateNameV1
  lang? = string
  baseUri? = anyURI
  branding? = "none" | "logo" | "name" | "nameAndLogo"
  addImageQuery? = boolean
  contentId? = string
  displayName? = string
  hint-textStacking? = "top" | "center" | "bottom"
  hint-overlay? = [0-100] >

  <!-- Child elements -->
  ( image
  | text
  | group
  )*

</binding>

接者是binding的部分有以上的attribute,這邊注意Child是可以做Grouping的喔!而template就是TileSmall、TileMedium、TileWide、TileLarge(只限桌面版本)。

  src = string
  placement? = "inline" | "background" | "peek"
  alt? = string
  addImageQuery? = boolean
  hint-crop? = "none" | "circle"
  hint-removeMargin? = boolean
  hint-align? = "stretch" | "left" | "center" | "right" />

以上的則是image的相關格式

  lang? = string
  hint-style? = textStyle
  hint-wrap? = boolean
  hint-maxLines? = integer
  hint-minLines? = integer
  hint-align? = "left" | "center" | "right" >

  <!-- text goes here -->

</text>


textStyle values...
  caption
  captionSubtle
  body
  bodySubtle
  base
  baseSubtle
  subtitle
  subtitleSubtle
  title
  titleSubtle
  titleNumeral
  subheader
  subheaderSubtle
  subheaderNumeral
  header
  headerSubtle
  headerNumber

接著是文字的XML。

最後是Grouping的XML格式

  <!-- Child elements -->
  subgroup+

</group>

<subgroup
  hint-weight? = [0-100]
  hint-textStacking? = "top" | "center" | "bottom" >

  <!-- Child elements -->
  ( text
  | image
  )*

</subgroup>

Group只能放個Subgroup然後Subgroup可以定義weight(Column)的比例!

假設定義了四個subgroup並都給予hint-weight都是1的話就會變成1/4(25%)

在subgroup裡面的text或image的xml都會是stack的方式堆疊

            var text2 = new TextElement() { StringData = "t2" };
            var image1 = new ImageElement() { ImageSource = "ms-appx:///Assets/Logo.png", IsRemoveMargin = true };
            var image2 = new ImageElement() { ImageSource = "ms-appx:///Assets/Logo.png", IsRemoveMargin = true };
            var subgroup1 = new SubGroupElement() { weight = 1, ChildElements = new ChildElement[] { text1, image1 } };
            var subgroup2 = new SubGroupElement() { weight = 1, ChildElements = new ChildElement[] { text2, image2 } };
            var group1 = new GroupElement() { Subgroups = new SubGroupElement[] { subgroup1, subgroup2 } };
            var group2 = new GroupElement() { Subgroups = new SubGroupElement[] { subgroup1, subgroup2 } };
            var visual = new VisualElement()
            {
                version = 3,
                BindingElements = new BindingElement[]
            {
                new BindingElement() { TileTemplate = AdaptiveTileSizeEnum.TileWide, Group = group1 },
                new BindingElement() { TileTemplate = AdaptiveTileSizeEnum.TileMedium, Group = group2 }
            }
            };
            var tile = new TileElement() { visual = visual };
            var notification = new TileNotification(AdaptiveTileHelper.TrySerializeToXml(tile));
            TileUpdateManager.CreateTileUpdaterForApplication().Update(notification);

上述程式碼就可以產生如以下圖片

image

image

 

詳細更多Adaptive tile資料請參考以下網址

 http://blogs.msdn.com/b/tiles_and_toasts/archive/2015/06/30/adaptive-tile-templates-schema-and-documentation.aspx 

 


 

 

接者來介紹Toast!之前在Windows 8.1的時候Toast會出現在右上角的角落,在8.1的Template只能顯示單張圖片以及簡單文字。在UWP的樣板一樣增加了Adaptive toast。

  <visual>
    <binding template="ToastGeneric">
      <text>Sample</text>
      <text>This is a simple toast notification example</text>
      <image placement="AppLogoOverride" src="oneAlarm.png" />
    </binding>
  </visual>
  <actions>
    <action content="check" arguments="check" imageUri="check.png" />
    <action content="cancel" arguments="cancel" />
  </actions>
  <audio src="ms-winsoundevent:Notification.Reminder"/>
</toast>

如上是簡單的Adaptive toast的XML樣板,可以看到一樣的是會有個visual為主要的視覺部分;action則是可以進行一些行為的動作;最後audio則是跳出toast的聲音。

image

       <visual addImageQuery="false" version="3">
              <binding addImageQuery="false" template="ToastGeneric">
                     <text>this is title</text>
                     <text>this is content</text>
                     <image addImageQuery="false" hint-crop="circle" placement="appLogoOverride" src="ms-appx:///Assets/Logo.png"/>
                     <image addImageQuery="false" hint-crop="none" placement="inline" src="ms-appx:///Assets/IC716666.png" alt="override"/>
              </binding>
       </visual>
</toast>

現在可以將圖片嵌入在toast的Content之中了!

image

       <visual addImageQuery="false" version="3">
              <binding addImageQuery="false" template="ToastGeneric">
                     <text>title</text>
                     <text>content</text>
                     <image addImageQuery="false" hint-crop="circle" placement="appLogoOverride" src="ms-appx:///Assets/Logo.png"/>
                     <image addImageQuery="false" hint-crop="none" placement="inline" src="ms-appx:///Assets/IC716666.png" alt="override"/>
                 </binding>
       </visual>
       <actions hint-systemCommand="SnoozeAndDismiss">
              <action content="primary" activationType="foreground" arguments="fitst"/>
              <action content="secondary" activationType="background" arguments="secondary"/>
       </actions>
</toast>

接者可以將Action加入在toast中。這邊需要注意的是要先用actions將兩個action包起來並且activation為foreground以及background。

image

       <visual addImageQuery="false" version="3">
              <binding addImageQuery="false" template="ToastGeneric">
                     <text>title</text>
                     <text>content</text>
                     <image addImageQuery="false" hint-crop="circle" placement="appLogoOverride" src="ms-appx:///Assets/Logo.png"/>
                     <image addImageQuery="false" hint-crop="none" placement="inline" src="ms-appx:///Assets/IC716666.png" alt="override"/>
              </binding>
       </visual>
       <actions hint-systemCommand="SnoozeAndDismiss">
              <input placeHolderContent="here" type="text" id="message">
       </actions>
</toast>

接者可以放入輸入框。這邊注意的是在input的type為text!

image

       <visual addImageQuery="false" version="3">
              <binding addImageQuery="false" template="ToastGeneric">
                     <text>title</text>
                     <text>content</text>
                     <image addImageQuery="false" hint-crop="circle" placement="appLogoOverride" src="ms-appx:///Assets/Logo.png"/>
                     <image addImageQuery="false" hint-crop="none" placement="inline" src="ms-appx:///Assets/IC716666.png" alt="override"/>
              </binding>
       </visual>
       <actions hint-systemCommand="SnoozeAndDismiss">
              <input type="selection" id="selections" defaultInput="2">
                     <selection content="s1" id="1"/>
                     <selection content="s2" id="2"/>
                     <selection content="s3" id="3"/>
              </input>
       </actions>
</toast>

還可以放入selections!。需要注意的是type變成selection而內部的selection都會有id來做為index的區別要和defaultinput為同樣的格式(以上就是用數字型態)。

新版的toast因為可以執行輸入data給App所以就得在加Code來做些邏輯判斷。

前景執行(Foreground execute)的狀態,或是說APP在執行狀態。

{
         if (args is ToastNotificationActivatedEventArgs)
         {
             var toastArgs = (ToastNotificationActivatedEventArgs)args;
             var toastArgument = toastArgs.Argument;
             var toastInput = toastArgs.UserInput["selections"];
         }
         base.OnActivated(args);
}

在App.xaml.cs檔案加入以上code的部分來進行擷取資料,這邊注意的是UserInput中的字串是在toast內的input的id!

背景執行(Background execute)的狀態,就是APP沒有在執行但toast跳出後的選擇後的執行方式。

	<BackgroundTasks>
		<Task Type="systemEvent"/>
		<Task Type="general"/>
	</BackgroundTasks>
</Extension>

先是註冊BackgroundTask在PackageManifest的Extension內,之前Preview版本使用的是systemEvent作為task的type但現在似乎轉為general!這個部分會等7/29上市後做測試。

然後寫上以下C#的程式碼註冊Background,而BackgroundTask的型態為ToastNotificationActionTrigger


 

接者建立BackgrountTask的C#檔案,並在其中寫入檔案中! 因為是背景啟動所以需要儲存為Storage。

    {
        public async void Run(IBackgroundTaskInstance taskInstance)
        {
		var deferral = taskInstance.GetDeferral();
        var localStorage = ApplicationData.Current.LocalFolder;
        var detail = taskInstance.TriggerDetails as ToastNotificationActionTriggerDetail;
		if (detail != null)
		{
			taskInstance.Canceled += TaskInstance_Canceled;
			...
			deferral.Complete();
    	}
	}

	private void TaskInstance_Canceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
	{

	}
}

接著在MainPage.cs的OnNavigationTo的事件中將Storage的資料轉換成Object狀態就可以處裡接下來的邏輯了。

PS:程式碼的部分之後會再補上

更新1 現在測試BackgroundTask(以Timer為例)變更如下

ToastNotificationManager.CreateToastNotifier("App").Show(toast);

如果不給ApplicationId會丟出錯誤!

更新2 Github的網址

https://github.com/EvaRichie/UWP1.0

 

詳細更多Adaptive toast資料請參考以下網址

http://blogs.msdn.com/b/tiles_and_toasts/archive/2015/07/02/adaptive-and-interactive-toast-notifications-for-windows-10.aspx


 

***以上Code以及說明都有可能隨著Windows 10 的版本以及Visual Studio 2015版本有所調整!***

參考資料 2-762 Tiles, Notifications and Action Center in Windows 10, MSDN Blogs

下次再分享Windows 10 的新技術拉~