Dieser Artikel ist Tag #11 der Serie 31 Tage Mango von Jeff Blankenburg.
Der Originalartikel befindet sich hier: Day #11: Live Tiles.
Heute beschäftigen wir uns mit Live Tiles für Windows Phone. Das ist ein vergleichsweise umfangreiches Thema — möglicherweise aber auch eines der wichtigsten der ganzen Serie. Auf zwei Punkte möchte ich heute besonders eingehen: wie man die Hauptkachel der Anwendung („Primary Tile“) aktualisiert und wie man weitere, zusätzliche Kacheln erstellt („Secondary Live Tiles“).
Was sind Live Tiles?
Falls Sie nicht selber ein Windows Phone besitzen, wissen Sie möglicherweise nicht, was für ein wesentlicher (und cooler) Bestandteil des Betriebssystems die Live Tiles sind. Beginnen wir deshalb mit einem kleinen Video meines Startbildschirms:
Um einer möglichen Enttäuschung gleich vorzubeugen: wir werden in diesem Artikel keine Live Tiles erstellen, die so lebendig und animiert aussehen wie in dem Video (wir können derzeit keine animierten Kacheln erstellen, abgesehen von den drehenden mit einer Rückseite). Wir werden unseren Anwendern aber neue Informationen präsentieren indem wir den Inhalt unserer Kachel aus der App aktualisieren. Dafür haben wir zwei Möglichkeiten: wir können die Standardwerte eines Live Tiles verändern oder wir können gleich den ganzen Hintergrund einer Kachel austauschen. Mit der zweiten Variante sind unserer gestalterischen Freiheit keine Grenzen gesetzt.
Ein entscheidender Punkt bevor wir anfangen ist: die Live Tiles befinden sich auf den Startbildschirm des Telefons und der Anwender entscheidet frei, welche Kacheln er gerne auf dem Startbildschirm sieht. Wenn Sie also Live Tiles verwenden, lassen Sie den Anwender wissen, dass er die Kachel auf den Startbildschirm pinnen sollte. Ansonsten werden die Anwender möglicherweise nichts von Ihren Bemühungen haben.
Der Standard Tile Ihrer Anwendung
Sobald Sie eine Anwendung beim Marketplace einreichen, haben Sie bereits Ihre erste Kachel erstellt. Die Daten dafür befinden sich in der Datei WPAppManifest.xml, welche im Ordner Properties eines jeden Windows Phone Projekts liegt. Auf zwei Stellen in dieser Datei möchte ich Sie besonders hinweisen: Die erste ist der App Title. Er hat nicht unmittelbar mit diesem Artikel zu tun, ist aber ein wichtiges Thema, das Sie im Auge behalten sollten. Wenn Sie die XML Datei öffnen, werden Sie eine Zeile wie die folgende finden (normalerweise die 4. Zeile):
<App xmlns="" ProductID="{1009dd75-9bef-4b08-9d0a-7518dafd777a}" Title="Day #11 - Live Tiles" RuntimeType="Silverlight" Version="1.0.0.0" Genre="apps.normal"Author="Jeff Blankenburg" Description="Sample description" Publisher="Jeff Blankenburg">
Die wichtigste Stelle hier ist die Eigenschaft Title. Wie im Bild unten zu erkennen, bestimmt der Text hier, was die Anwender sehen wenn sie die Liste der Anwendungen durchsehen.
Der andere wichtige Teil befindet sich ziemlich am Ende der XML Datei (normalerweise Zeile 25) im Knoten <Tokens>. Der <PrimaryToken> unserer heutigen Anwendung sieht beispielsweise so aus:
<Tokens> <PrimaryToken TokenID="Day11_LiveTilesToken" TaskName="_default"> <TemplateType5> <BackgroundImageURI IsRelative="true" IsResource="false">Background.png</BackgroundImageURI> <Count>20</Count> <Title>Jeff Blankenburg</Title> </TemplateType5> </PrimaryToken> </Tokens>
Die entscheidenden Werte hier sind BackgroundImageURI, Count und Title. Das sind die Eigenschaften, die wir im Laufe dieses Artikels manipulieren werden und im Knoten <Tokens> in der Datei WMAppManifest.xml können Sie die Startwerte festlegen (ich verwende hier die Background.png aus der Projektvorlage. Wenn Sie die Anwendung beim Windows Phone Marketplace einreichen wollen, können Sie dieses Standardsymbol nicht verwenden — Ihre Anwendung würde abgelehnt werden).
Mit den Werten von oben hätten wir folgende Kachel erstellt:
Wie Sie sehen, wird die Eigenschaft Count als kleiner, schwarzer Kreis mit weißer Schrift dargestellt. Der Wert der Eigenschaft Title wird auf dem Tile unten mit weißer Schrift dargestellt. Die Farben, Größen und das Layout ändert sich nicht — auch nicht, wenn der Anwender die Farbeinstellungen seines Handys umstellt. Die Eigenschaft BackgroundImageURI nutzt ein Bild, um den Hintergrund der Kachel auf der ganzen Fläche auszufüllen. Wenn die Bilddatei nicht die Abmessungen 173x173 Pixel hat, wird sie entsprechend gestreckt. Ich empfehle also dringend, ein Bild in den Abmessungen 173x173 Pixel zu verwenden.
Jetzt, wo wir die anfängliche Kachel für unsere Anwendung erstellt haben, können wir uns im Rest des Artikels damit beschäftigen, wie wir die Inhalte der Kacheln dynamisch verändern (ja, Kacheln sind hier absichtlich im Plural).
Den Standard Tile aktualisieren
Wie zu Beginn erwähnt, können Sie sowohl den Inhalt des Standard Tiles verändern als auch weitere („Secondary“) Tiles erstellen und verändern. In diesem Abschnitt wollen wir uns zunächst mit dem Standard Tile beschäftigen. Die Secondary Tiles folgen im zweiten Teil des Artikels. Es gibt viele verschiedene Möglichkeiten zur Aktualisierung des Live Tiles. Damit Sie einen Eindruck bekommen, was alles möglich ist, beginne ich wieder mit einem kleinen Video unserer fertigen Anwendung.
Zunächst müssen wir wieder eine Oberfläche bauen. Dafür brauchen wir die Icons für den Smiley und das traurige Gesicht. Sie können die beiden Symbole hier in der passenden Größe herunterladen:
Bevor Sie die Symbole verwenden können, müssen Sie diese Ihrem Projekt hinzufügen und den Content Type in den Visual Studio Eigenschaften auf „Content“ setzen. Falls Sie das vorher noch nicht gemacht haben: Klicken Sie rechts auf Ihr Projekt und wählen „Add Existing Item…“ (Anm. leitning: Sorry, ich habe selber nur ein englisches Visual Studio und weiß gerade nicht auswendig, wie der Menüpunkt im deutschen Visual Studio heißt).
Sobald die Bilder in Ihrem Projekt sind, wird ein Klick auf diese die Eigenschaften öffnen. Hier sollten Sie sicherstellen, dass die Build Action auf „Content“ anstatt „Resource“ steht.
Die Bilder sind jetzt vorbereitet. Das folgende XAML können Sie verwenden, um eine Oberfläche wie diese hier zu erstellen:
Sie sehen im XAML, dass wir zwei Image Controls, einen Slider, einen TextBlock, eine TextBox und zwei Buttons haben. Diese Controls werden uns erlauben, den Live Tile anzupassen.
<phone:PhoneApplicationPage x:Class="Day11_LiveTiles.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" shell:SystemTray.IsVisible="True"> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="31 DAYS OF MANGO - DAY #11" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="live tiles" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <TextBlock Text="primary tile" Height="40" VerticalAlignment="Top" FontSize="26.667" /> <Image x:Name="SadButton" Source="images/sadface.png" Width="150" Height="150" Margin="191,48,115,0" VerticalAlignment="Top" MouseLeftButtonDown="SadButton_MouseLeftButtonDown" Opacity=".5" /> <Image x:Name="SmileButton" Source="images/smiley.png" Width="150" Height="150" HorizontalAlignment="Left" Margin="21,48,0,0" VerticalAlignment="Top" MouseLeftButtonDown="SmileButton_MouseLeftButtonDown" Opacity=".5" /> <Slider x:Name="CountSlider" Margin="8,198,102,0" Foreground="Green" Maximum="99" ValueChanged="CountSlider_ValueChanged" Height="84" VerticalAlignment="Top"/> <TextBox x:Name="TitleText" Margin="8,250,102,288" TextWrapping="Wrap"/> <TextBlock x:Name="SliderText" HorizontalAlignment="Right" Margin="0,181,12,0" TextWrapping="Wrap" Text="0" Width="90" FontSize="64" Height="84" VerticalAlignment="Top" TextAlignment="Center"/> <TextBlock Text="secondary tile" Height="40" VerticalAlignment="Bottom" FontSize="26.667" Margin="0,0,0,133" /> <Button x:Name="SecondaryButton" Content="create a secondary tile" Height="75" Margin="5,0,102,56" VerticalAlignment="Bottom" Click="SecondaryButton_Click"/> <Button x:Name="PrimaryButton" Content="update primary tile" Height="75" Margin="9,0,102,204" VerticalAlignment="Bottom" Click="PrimaryButton_Click"/> </Grid> </Grid> </phone:PhoneApplicationPage>
Abgesehen von den neuen Controls im ContentPanel handelt es sich bei dem XAML um den Standard Code, den das Visual Studio bei einem neuen Projekt für die MainPage.xaml anlegt.
Das entscheidende Stückchen Code in diesem Abschnitt ist jenes, welches ausgeführt wird, wenn der Anwender auf den Button „update primary tile“ klickt. Der Code des Event Handlers PrimaryButton_Click sieht etwa so aus:
private void PrimaryButton_Click(object sender, RoutedEventArgs e) { ShellTile PrimaryTile = ShellTile.ActiveTiles.First(); if (PrimaryTile != null) { StandardTileData tile = new StandardTileData(); tile.BackgroundImage = new Uri("images/sadface.png", UriKind.Relative); tile.Count = (Int32)Math.Round(CountSlider.Value, 0); tile.Title = TitleText.Text; PrimaryTile.Update(tile); } }
Wir holen uns eine Referenz auf den Primary Tile indem wir das First() Element der ActiveTiles Collection abfragen. Diese Collection enthält nicht nur den Primary Tile (dieser ist aber immer der erste), sondern auch alle weiteren Secondary Tiles, die Sie erstellt haben.
Ich habe ein neues StandardTileData Objekt angelegt und die Eigenschaften so gesetzt, dass das traurige Gesicht als Hintergrundbild verwendet wird, der Wert der Eigenschaft Count dem Wert des Sliders entspricht und der Title den Wert der TextBox bekommt. Dann rufen wir die Methode Update() auf dem ShellTile Objekt des Standard Tiles auf und übergeben die neuen Tile Daten. Mehr ist nicht nötig um den Tile zu aktualisieren. Natürlich müssen Sie nicht alle Eigenschaften mit Werten belegen.
Wenn Sie eine Wetter-Anwendung entwickeln, möchten Sie möglicherweise die aktuelle Temperatur in der Eigenschaft Count darstellen. Die anderen Werte würden dann unverändert bleiben. Wo wir beim Beispiel der Temperatur sind: Die Eigenschaft Count hat einen Maximalwert von 99. Es gibt aber Orte mit einer höheren Temperatur als 99 Grad (Anm. leitning: Jeff bezieht sich hier auf Temperatur in Grad Fahrenheit). Für diese Fälle gibt es eine bessere Lösung.
Eine einfache Variante wäre, einen Haufen von Bildern mit allen möglichen Werten zu erstellen und diese dem Projekt hinzuzufügen. Dann könnten Sie einfach die Eigenschaft BackgroundImage auf das entsprechende Bild setzen und hätten einen passenden Temperatur-Tile. Mit hunderten von Bildern würde diese Lösung Ihre Anwendung ziemlich aufblähen.
Zum Glück können wir auch Bilder verwenden, die auf einem Webserver liegen. In diesem Fall geben wir für die Eigenschaft BackgroundImage einfach die URI zum entsprechenden Bild an, wie im folgenden Beispiel zu sehen:
tile.BackgroundImage = new Uri("http://jeffblankenburg.com/images/jeff.png");
Ich habe das mit unterschiedlichen Bildformaten ausprobiert und es scheint nur mit PNG Bildern zu funktionieren. Das sollten Sie im Hinterkopf behalten, wenn Sie diese Technik verwenden wollen. Wenn Sie eine endliche Anzahl von Bildern haben, ist die Ablage auf einem Webserver eine hervorragende Möglichkeit, dem Anwender abhängig von den Bedingungen eine passende Kachel anzuzeigen — wie in unserem Fall zum Beispiel 27 Grad und wolkig.
Einen Secondary Tile erstellen
Bisher haben wir uns nur mit der Hauptkachel der Anwendung beschäftigt. Wenden wir uns den Secondary Tiles zu. Dies sind weitere Kacheln, die Ihr Benutzer aus der Anwendung heraus auf die Startseite pinnen kann.
Als Beispiel stellen Sie sich eine Anwendung vor, die verschiedene Spiele beinhaltet. Sie können mit der Anwendung z.B. Tic Tac Toe, Wörter raten und Hangman spielen. Normalerweise müsste Ihr Anwender die Anwendung aus der Anwendungsliste öffnen, das Spiel wählen um dieses dann schließlich zu spielen. Mit Secondary Tiles können Sie Ihrem Anwender erlauben, separate Tiles für jedes Spiel zu erstellen, so dass sie z.B. Hangman direkt von ihrer Startseite aus spielen können. Mit dem Secondary Tile haben Sie dem Anwender eine Abkürzung in einen bestimmten Lieblingsbereich der Anwendung gebaut.
Um einen Secondary Tile anzulegen, brauchen wir fast den selben Code wie beim Primary Tile. Es gibt nur einige kleine Unterschiede. Erstens: der entsprechende Secondary Tile kann aber muss nicht da sein, wenn Sie nach ihm suchen (der Primary Tile ist auch dann in der Collection, wenn die Anwendung nicht auf die Startseite gepinnt ist). Ein Secondary Tile verschwindet aus der Collection, wenn der Anwender diesen von der Startseite entfernt.
Die Event Handler Methode SecondaryButton_Click, die wir im obigen XAML bereits registriert hattten, findet sich im folgenden Codebeispiel:
private void SecondaryButton_Click(object sender, RoutedEventArgs e) { ShellTile SecondaryTile = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("ID=2")); StandardTileData tile = new StandardTileData(); if (SecondaryTile == null) { tile.BackgroundImage = new Uri("images/yoda.png", UriKind.Relative); tile.Title = "Beware..."; tile.BackTitle = "The Dark Side"; tile.BackBackgroundImage = new Uri("images/darthvader.png", UriKind.Relative); tile.BackContent = "I...am your father."; ShellTile.Create(new Uri("/DeepLink.xaml?ID=2", UriKind.Relative), tile); } }
Wie Sie im Beispiel sehen, verwende ich etwas LINQ, um den gewünschten Live Tile zu finden. Ich suche in der ActiveTiles Collection nach einem Tile, dessen NavigationUri „ID=2“ enthält. Ich erkläre das am besten vom Ende her.
Wenn Sie einen Secondary Tile erstellen, rufen Sie die Methode ShellTile.Create() auf. Dieser übergeben Sie eine URI und ein zuvor erstelltes StandardTileData Objekt. Die URI zeigt auf eine bestimmte Seite innerhalb Ihrer Anwendung und es kann nicht zwei Secondary Tiles geben, die die selbe URI haben. Die URI ist somit ein eindeutiger Identifikator für den Secondary Tile. Deshalb können wir oben die Collection per LINQ nach der entsprechenden URI durchsuchen. Sollten mehrere Secondary Tiles auf die selbe Seite innerhalb Ihrer Anwendung zeigen aber dort unterschiedliche Daten anzeigen, können Sie Query String Variablen mit übergeben um die URI eindeutig zu machen. Die Suche nach einem bestimmten Tile zielt dann nicht auf den Seitennamen, sondern auf den Query String, wie in unserem Beispiel oben.
Wenn die Suche den entsprechenden Tile nicht in der Collection gefunden hat, können wir ihn wie im obigen Beispiel neu anlegen. Wie Sie sehen, handelt es sich um das selbe StandardTileData Objekt wie oben, nur dass wir diesmal drei weitere Eigenschaften setzen (die drei weiteren Eigenschaften können Sie auch für den Primary Tile setzen — ich wollte das nur für etwas später im Artikel aufsparen).
Um zu zeigen, was die drei neuen Eigenschaften machen, folgt hier wieder ein kleines Video:
Sobald Sie eine der Eigenschaften BackTitle, BackBackgroundImage oder BackContent setzen, wird Ihr Tile automatisch umdrehen. Das Betriebssystem bestimmt, wann der Tile umdreht. Sie können nur festlegen, dass er sich umdrehen soll. Die Rückseite der Kachel hat übrigens keine Eigenschaft Count. Die Vorderseite hat dafür keine Eigenschaft Content (für den größer auf der Rückseite dargestellten Text). Hier sind zwei Screenshots mit der Vorder- und der Rückseite unserer Kachel:
Sie können Ihrem Anwender erlauben, beliebig viele Secondary Tiles zu erstellen. Wichtig dabei ist nur folgendes:
- Jeder Live Tile muss auf eine eindeutige URI verweisen.
- Jedes Mal, wenn Sie einen neuen Tile erstellen, wird der Anwender zur Startseite wechseln um den neuen Tile zu sehen. Sie können nicht mehrere Secondary Tiles auf einmal erstellen.
- Alle Eigenschaften in den obigen Codebeispielen funtionieren sowohl für den Primary Tile als auch für die Secondary Tiles.
- Es ist nicht immer eine gute Idee, die Startseite des Anwenders mit Live Tiles vollzupflastern. Erstellen Sie keinen Secondary Tile, wenn es nicht einen guten Grund dafür gibt. Die Anwender könnten sonst schnell genervt sein.
Zusammenfassung
Das Video in diesem Artikel sollte ganz gut illustriert haben, wie sich die Live Tiles einer Anwendung verhalten. Sie sind ein sehr wichtiges Mittel bei der Interaktion mit dem Anwender. Wenn Sie dem Anwender relevante Informationen auf der Startseite anzeigen, werden diese nicht nur erinnert, Ihre Anwendung zu benutzen, sie sind auch in der Lage, alle wichtigen Informationen direkt auf der Startseite im Überblick zu haben.
Wenn Sie mit der voll funktionsfähigen Anwendung dieses Artikels herumexperimentieren möchten, klicken Sie auf den Download Code Button.
Morgen unterhalten wir uns über ein sehr wichtiges Thema für eine erfolgreiche Anwendung: Beta Testing. Mein Gastautor Jared Bienz wird Ihnen genau zeigen, wie Sie Ihre Anwendung beta-testen können und wie diese davon profitieren wird.
Bis dahin!