poniedziałek, 2 kwietnia 2012

Notatki o Windows 8 Consumer Preview - odc. 5

Tym razem na temat wyszukiwania, ustawień aplikacji, helpa, splash screen oraz kafelków (cz.1)

W porównaniu z poprzednią wersją więcej dowiadujemy się o ustawieniach aplikacji w JS i XAML (widać też całkiem spore różnice w implementacji). Dostajemy pomysł “wizualnego przedłużania” splash screen, dzięki czemu nasza aplikacja na starcie może znacznie zyskać wizualnie.

Najwięcej zmian odnotowujemy w kafelkach.  Obecnie mamy szczegółowo przedstawione wizualnie i opisane wszystkie szablony do ich aktualizacji (jest ich naprawdę dużo!). Okazuje się, że aktualizację kafelków może wyłączyć nam administrator (poza ustawieniami aplikacji), a aplikacja może w pewnych przypadkach to sprawdzić i poprosić użytkownika o włączenie notyfikacji!  Za jednym razem możemy wysłać notyfikacje do odświeżenia kafelka square i wide. Dostajemy także wizualizacje graficzne odznaczeń (badges). Notyfikacje do kafelków i odznaczeń mogą być programowo usuwane. Dalsze zagadnienia związane z kafelkami i notyfikacjami w kolejnym poście.

JS

Search

An activated event:

var detail = e.detail;// Check if this is search activationif (detail.kind === Windows.ApplicationModel.Activation.ActivationKind.search) {

If you provide both types of search suggestions (queries and results), you should provide only one result suggestion and it should be displayed last, at the bottom of the list of suggestions.

While the user enters a search query, Windows automatically provides suggestions for possible queries in the search pane. These suggestions are based on the user’s search history with your app and will be shown first, before suggestions that your app provides are displayed.

IC573271

Navigate to your search results page while responding to Search activation when your app is snapped.

If your app is snapped when the user uses it to search (causing the search activated event to fire) your app automatically unsnaps (causing the unsnap event to fire) and becomes the main app on screen.

App settings

Specify the commands to be exposed in Settings
  1. Listen for the settings pane's CommandsRequested event.
  2. Specify the commands in the associated callback. For each command:

    1. Provide a SettingsCommand.Id and a localized SettingsCommand.Label.
    2. Set the handler (SettingsCommand.Invoked) for the event that will be fired when the user selects the command.
    3. Append the SettingsCommand object to the ApplicationCommands vector to make it available to the SettingsPane.
Show the appropriate custom settings when user asks for them
  • Show the appropriate app-defined settings UI in response to the user invocation of a settings command.
  • Keep the UI for this simple, and dismissible with a touch, to keep the user in the current app context.
  • Reflect settings changes in the app instantly.

function initializeSettings() { // Initialize all settings flyouts and WinJS controls. WinJS.UI.processAll(); // Populate settings pane and tie commands to settings flyouts. WinJS.Application.onsettings = function (e) { e.detail.applicationcommands = { "defaultsDiv": { href: "DefaultsUI.html", title: "Defaults"}, "helpDiv": { href: "HelpUI.html", title: "Help"} }; WinJS.UI.SettingsFlyout.populateSettings(e); } WinJS.Application.start();}

<!doctype HTML><html> <head> <title>Defaults settings flyout</title> </head> <body> <!-- BEGINTEMPLATE: Template code for an empty Settings Flyout. --> <!-- Each settings flyout should be defined in its own HTML file. --> <!-- Set the width to 'narrow' for a narrow settings flyout. --> <!-- Set the background color for the header to the background color defined for your app tile in the manifest. --> <div id="defaultsDiv" data-win-control="WinJS.UI.SettingsFlyout" aria-label="App defaults settings flyout" data-win-options="{width:'wide'}"> <div class="win-header" background-color:#dbf9ff"> <button type="button" onclick="WinJS.UI.SettingsFlyout.show()" class="win-backbutton"></button> <div class="win-label">Defaults</div> <img src="images/smallTile.png" style="position: absolute; right: 40px;"/> </div> <div class="win-content"> {Defaults content here} </div> </div> <!-- ENDTEMPLATE --> </body></html>

The settings window includes both app and system settings.

The app may provide SettingsCommand entry points, which appear at the top of the settings window. Two entry points, Permissions, and Rate and review, are provided by the system. The bottom of the settings window includes PC settings provided by the system, like volume, brightness, and power.

Only apps that are installed through the Windows Store have the Rate and review entry point. Side-loaded enterprise apps don't have this entry point.

The entry points open settings Flyouts, which contain the app’s settings, help, About info, and any secondary commands or information that your users would access infrequently. An app can have multiple entry points for settings, and each settings Flyout can have multiple options.

Use a light-dismiss surface, so that the settings Flyout disappears when the user touches anywhere on the screen outside of the surface. This enables the user to quickly change a setting and get back to the app. The UI created through the SettingsFlyout classes is a light-dismiss surface. If you create your own UI, make sure that your settings Flyout is dismissed when the user touches the application (on contact down), when the app loses activation, such as when the charms are opened, and when the app is snapped.

Use an additional level of UI or an expand/collapse model to repeat settings exposed under multiple objects listed in the UI. For example, a weather app that provides per-city settings should provide the list of cities that can be configured in the first settings level and let the user tap on the city to get to the next level to configure options there. A mail app that supports multiple accounts should show the list of accounts and let the user tap on an account to open the corresponding second-level settings UI.

App help

{ var n = Windows.UI.ApplicationSettings; var settingsPane = n.SettingsPane.getForCurrentView();var vector = settingsPane.applicationCommands;//Ensure no settings commands are currently specified in the settings charm vector.clear();// Add a known settings command to the settings charmvar commandPreferences = new settingsSample.SettingsCommand(n.KnownSettingsCommand.help, OnHelp); vector.append(commandHelp);// Add a custom settings command to the settings charmvar commandParameters = new n.SettingsCommand("Custom.Parameters", "Parameters", OnParameters);vector.append(commandParameters);}function OnHelp() { //show Preferences UI when preferences is selected }function OnParameters() { //show Parameters UI when preferences is selected }

Splash screen

VS: Open the Application UI tab and scroll down to the Splash Screen section. In the Background Color field of the Splash Screen section, set the background color to display with your splash screen image. Setting a background color for your splash screen is optional. If you do not specify a color, the splash screen background color defaults to the Tile background color (the color in the Background Color field of the Tile section in the Application UI tab).

You can display a splash screen for longer by creating and displaying a view that imitates the splash screen that is displayed by Windows while your app loads. You may want to display a splash screen for longer if you want to show real-time loading information to users or simply if your app needs more time to load.

To give users the impression that the splash screen is shown for longer, your view must accurately imitate the splash screen that is shown by Windows in at least these ways:

  • Your view should use a 620 x 300 pixel image that is consistent with the image specified for your splash screen in your app manifest (your app's splash screen image).
  • Your view should use a background color that is consistent with the background color specified for your splash screen in your app manifest (your app's splash screen background).
  • Your code should position the image that you use in your view at the same screen coordinates where Windows positioned your app's splash screen image when Windows displayed the splash screen.

For example, the Splash screen sample uses the following two files to define its imitation splash screen view:

  • "extended-splash.html"
  • "extended-splash.css"

Create a smooth transition to your app by mimicking the splash screen while your app loads.

When you use the splash screen API to make your app's first view mimic the splash screen, you can control your users' experience as your app loads. For example, if your app needs more time to load resources, you can use your imitation splash screen to display additional loading information. This hides the multi-step loading process from users, giving them a smooth and informative loading experience.

You can see an example of the users' loading experience in these images, which depict the transition to an app that uses an imitation splash screen.

IC536078

Tiles & badges (1)

Tiles

IC563426

var tileXml = Notifications.TileUpdateManager.getTemplateContent(Notifications.TileTemplateType.tileWideText03);

var tileAttributes = tileXml.getElementsByTagName("text"); tileAttributes[0].appendChild(tileXml.createTextNode("Hello World! My very own tile notification"));

var tileNotification = new Notifications.TileNotification(tileXml);

tileNotification.expirationTime = new Date(currentTime.getTime() + 600 * 1000);

Notifications.TileUpdateManager.createTileUpdaterForApplication().update(tileNotification);

A square and wide tile in the same notification

var tileXml = Notifications.TileUpdateManager.getTemplateContent(Notifications.TileTemplateType.tileWideImageAndText01); // Get the text attributes for this template and fill them in.var tileTextAttributes = tileXml.getElementsByTagName("text"); tileTextAttributes[0].appendChild(tileXml.createTextNode("This tile notification uses ms-resource images")); // Get the image attributes for this template and fill them in.var tileImageAttributes = tileXml.getElementsByTagName("image"); tileImageAttributes[0].setAttribute("src", "ms-resource:images/redWide.png");

var squareTileXml = Notifications.TileUpdateManager.getTemplateContent(Notifications.TileTemplateType.tileSquareImage); var squareTileImageAttributes = squareTileXml.getElementsByTagName("image"); squareTileImageAttributes[0].setAttribute("src", "ms-resource:images/graySquare.png");

var node = tileXml.importNode(squareTileXml.getElementsByTagName("binding").item(0), true); tileXml.getElementsByTagName("visual").item(0).appendChild(node);

<tile> <visual lang="en-US> <binding template="TileSquareImage"> <image id="1" src="ms-appx:///images/graySquare.png"/> </binding> <binding template="TileWideImageAndText01"> <image id="1" src="ms-appx:///images/redWide.png"/> <text id="1">This tile notification uses ms-resource images</text> </binding> </visual></tile>

The notification queue with local notifications

Windows.UI.Notifications.TileUpdateManager.createTileUpdaterForApplication().enableNotificationQueue(true);

tileNotification.tag = "stock.msft";

Clear a tile notification

Windows.UI.Notifications.TileUpdateManager.createTileUpdaterForApplication().clear();

For a tile with the notification queue enabled and notifications in the queue, calling the clear method empties the queue.

Note that you cannot clear a notification through the cloud. While a local call to the clear method will clear the tile regardless of the source of its notifications, to clear a notification from the tile through a periodic or push notification, you should send a new notification to replace the current content.

Check whether a tile can be updated

Step 1: Retrieve the notification setting

This code shows how to retrieve and handle the tile notification setting. Most apps will never call this API. In general, an app should use this setting to determine if it should update the tile with local content from the app itself. You should not use this setting to tell your cloud service not to push notifications.

var notificationSetting = Windows.UI.Notifications.TileUpdateManager.createTileUpdaterForApplication().setting;

There are legitimate scenarios where an app could suggest to the user that they enable notifications, such as the receipt of an instant message when the user has disabled notifications in the messaging app. However, make sure that the situation is important enough to warrant the request and do not badger the user to make the change.

Tile update templates

Square tiles

Square text-only templates

TileSquareBlock

TileSquareBlock example

TileSquareText01

TileSquareText01 example

TileSquareText02

TileSquareText02 example

TileSquareText03

TileSquareText03 example

TileSquareText04

TileSquareText04 example

Square image-only templates

TileSquareImage

TileSquareImage example

Square peek templates (top/bottom)

TileSquarePeekImageAndText01

TileSquarePeekImageAndText01 example 

TileSquarePeekImageAndText02

TileSquarePeekImageAndText02 example 

TileSquarePeekImageAndText03

TileSquarePeekImageAndText03 example 

TileSquarePeekImageAndText04

TileSquarePeekImageAndText04 example

Wide tiles

Wide text-only templates
TileWideText01

TileWideText01 example
TileWideText02

TileWideText02 example
TileWideText03

TileWideText03
TileWideText04

TileWideText04 example
TileWideText05

TileWideText05 example
TileWideText06

TileWideText06 example
TileWideText07

TileWideText07 example
TileWideText08

TileWideText08 example
TileWideText09

TileWideText09 example
TileWideText10

TileWideText10 example
TileWideText11

TileWideText11 example
 
Wide image-only templates
TileWideImage

TileWideImage example
TileWideImageCollection

TileWideImageCollection example
Wide image-and-text templates
TileWideImageAndText01

TileWideImageAndText01 example
TileWideImageAndText02

TileWideImageAndText02 example
TileWideBlockAndText01

TileWideBlockAndText01 example
TileWideBlockAndText02

TileWideBlockAndText02 example
TileWideSmallImageAndText01

TileWideSmallImageAndText01 example
TileWideSmallImageAndText02

TileWideSmallImageAndText02 example
TileWideSmallImageAndText03

TileWideSmallImageAndText03 example
TileWideSmallImageAndText04

TileWideSmallImageAndText04 example
 
Wide peek templates (top/bottom)
TileWidePeekImageCollection01

TileWidePeekImageCollection01 example
TileWidePeekImageCollection02

TileWidePeekImageCollection02 example
TileWidePeekImageCollection03

TileWidePeekImageCollection03 example
TileWidePeekImageCollection04

TileWidePeekImageCollection04 example
TileWidePeekImageCollection05

TileWidePeekImageCollection05 example
TileWidePeekImageCollection06

TileWidePeekImageCollection06 example
TileWidePeekImageAndText01

TileWidePeekImageAndText01 example
TileWidePeekImageAndText02

TileWidePeekImageAndText02 example
TileWidePeekImage01

TileWidePeekImage01 example
TileWidePeekImage02

TileWidePeekImage02 example
TileWidePeekImage03

TileWidePeekImage03 example
TileWidePeekImage04

TileWidePeekImage04 example
TileWidePeekImage05

TileWidePeekImage05 example
TileWidePeekImage06

TileWidePeekImage06 example

var tileXml = Windows.UI.Notifications.TileUpdateManager.getTemplateContent(template);

var tileImageAttributes = tileXml.getElementsByTagName("image");

Assign a local image from the app's package to the template element. We also assign alt text for accessibility purposes such as screen readers.

tileImageAttributes[0].setAttribute("src", "ms-appx:///images/redWide.png"); tileImageAttributes[0].setAttribute("alt", "red graphic");

Assign a local image from the app's local storage to the template element

tileImageAttributes[0].setAttribute("src", "ms-appdata:///local/redWide.png");

Assign a web image to the template element. You can also use the https:// protocol.

tileImageAttributes[0].setAttribute("src", "http://www.microsoft.com/redWide.png");

The visual element in the tile notification XML payload contains the baseUri attribute. The value of the baseUri attribute provides a base path such as "http://www.microsoft.com/" that is combined with relative Uniform Resource Identifiers (URIs) in the image src attribute.

tileImageAttributes[0].setAttribute("src", "redWide.png");

Troubleshooting

The user or administrator has disabled notifications through settings. Check whether the app has supplied a Turn live tile on/off option in the app bar, and that it isn't turned to "off". As for the administrator, there are several group policies which can disable notifications. Check with your administrator to ensure that notifications are enabled.

Images for all notifications must be smaller than 800 x 800 pixels and less than 150 KB in size. If any image in a notification exceeds any of these dimensions, the notification will be discarded.

Notifications can only use images in .png or .jpg/.jpeg format. The format of the image must also match its extension.

By default, tiles display only one update at a time and a new incoming notification replaces the existing one. If you want to display the last five notifications in a rotation, you must call TileUpdater.EnableNotificationQueue(true) in your app's initiation code. This needs to be done only once in your app's lifetime.

Updating badges

The badge catalog is not extendable. Only the Windows-provided images listed in this topic can be used on a tile.

numeric

A badge displaying the number 1
none

activity

The activity badge; two circling arrows
alert

The alert badge
available

The available badge; a green dot
away

The away badge; a yellow dot
busy

The busy badge; a red dot
newMessage

The new mail badge; an envelope
paused

The paused badge
playing

The playing badge
unavailable

The unavailable badge; a gray dot
error

The error badge; an X

var badgeXml = Notifications.BadgeUpdateManager.getTemplateContent(Notifications.BadgeTemplateType.badgeNumber);

var badgeXml = Notifications.BadgeUpdateManager.getTemplateContent(Notifications.BadgeTemplateType.badgeGlyph);

var badgeAttributes = badgeXml.getElementsByTagName("badge"); badgeAttributes[0].setAttribute("value", "7");

var badgeAttributes = badgeXml.getElementsByTagName("badge"); badgeAttributes[0].setAttribute("value", "newMessage");

var badgeNotification = new Notifications.BadgeNotification(badgeXml); Notifications.BadgeUpdateManager.createBadgeUpdaterForApplication().update(badgeNotification);

This code removes any badge currently shown on the calling app's tile.

Windows.UI.Notifications.BadgeUpdateManager.createBadgeUpdaterForApplication().clear();

Don't repeat badge numbers elsewhere in a wide tile's body content, because the two instances could be out of sync at times.

C#

App settings

Implementing the Settings contract by using XAML and the ApplicationSettings class.

You create a settings Flyout control that's hosted in a Popup control. The settings Flyout is associated with a SettingsCommand that's added to an ApplicationCommands collection.

public sealed partial class SimpleSettingsNarrow : UserControl {

public SimpleSettingsNarrow() { this.InitializeComponent(); }

private void MySettingsBackClicked(object sender, RoutedEventArgs e) { if (this.Parent.GetType() == typeof(Popup)) { ((Popup)this.Parent).IsOpen = false; } SettingsPane.Show(); } }

public sealed partial class BlankPage : Page {

Rect _windowBounds; double _settingsWidth = 346; Popup _settingsPopup;

public BlankPage() { this.InitializeComponent(); _windowBounds = Window.Current.Bounds; Window.Current.SizeChanged += OnWindowSizeChanged; SettingsPane.GetForCurrentView().CommandsRequested += BlankPage_CommandsRequested; }

void OnWindowSizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e) { _windowBounds = Window.Current.Bounds; }

void BlankPage_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args) { SettingsCommand cmd = new SettingsCommand("sample", "Sound Options", (x) => { _settingsPopup = new Popup(); _settingsPopup.Closed += OnPopupClosed; Window.Current.Activated += OnWindowActivated; _settingsPopup.IsLightDismissEnabled = true; _settingsPopup.Width = _settingsWidth; _settingsPopup.Height = _windowBounds.Height; SimpleSettingsNarrow mypane = new SimpleSettingsNarrow(); mypane.Width = _settingsWidth; mypane.Height = _windowBounds.Height; _settingsPopup.Child = mypane; _settingsPopup.SetValue(Canvas.LeftProperty, _windowBounds.Width - _settingsWidth); _settingsPopup.SetValue(Canvas.TopProperty, 0); _settingsPopup.IsOpen = true; }); args.Request.ApplicationCommands.Add(cmd); }

private void OnWindowActivated(object sender, Windows.UI.Core.WindowActivatedEventArgs e) { if (e.WindowActivationState == Windows.UI.Core.CoreWindowActivationState.Deactivated) { _settingsPopup.IsOpen = false; } }

void OnPopupClosed(object sender, object e) { Window.Current.Activated -= OnWindowActivated; }

/// <summary> /// Invoked when this page is about to be displayed in a Frame. /// </summary> /// <param name="e">Event data that describes how this page was reached. The Parameter /// property is typically used to configure the page.</param> protected override void OnNavigatedTo(NavigationEventArgs e) { }

private void Button_Click_1(object sender, RoutedEventArgs e) { SettingsPane.Show(); }

private void HandleSizeChange(object sender, RoutedEventArgs e) { RadioButton rb = sender as RadioButton; _settingsWidth = Convert.ToInt32(rb.Content); } }

Tiles & badges (1)

XmlDocument tileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWideText03);

XmlNodeList tileTextAttributes = tileXml.GetElementsByTagName("text");int index = 1;foreach (XmlNode tileTextAttr in tileTextAttributes){ tileTextAttr.InnerText = "textField " + Convert.ToString(index); index++;}

TileNotification tileNotification = new TileNotification(tileXml);

tileNotification.ExpirationTime = DateTimeOffset.UtcNow.AddSeconds(10);

TileUpdateManager.CreateTileUpdaterForApplication().Update(tileNotification);

If you send a wide tile in a notification, you should also send a square tile because you are not guaranteed which will be displayed.

Brak komentarzy: