I’m writing a Windows Phone app and I want it to have Live Tiles. However I want it to show a Count on the front of the Live tile which is larger than 99. Currently any number larger than 99 shows 99 as the count. I wanted to show bigger numbers and therefore from what I can gather, I had to roll my own for this. I have done so by drawing my own Live Tile background image.
Drawing a custom image was pretty easy on Windows Mobile or on any other platform with GDI+ support. However in Windows Phone and Silverlight its a little harder. I found a great tool called WriteableBitmapEx (http://writeablebitmapex.codeplex.com/). This great tool gives GDI+ style methods as extension methods on a Writeable Bitmap. I was then able to use this to draw the count like this:
// Define the filename for our tile. Take note that a tile image *must* be saved in /Shared/ShellContent
// or otherwise it won't display.
var tileImage = string.Format("/Shared/ShellContent/{0}.jpg", myUniqueTileId);
var source = new BitmapImage();
source.CreateOptions = BitmapCreateOptions.None;
var imageUri = new Uri(theEvent.ImagePath.Substring(1), UriKind.Relative);
System.Windows.Resources.StreamResourceInfo s = Application.GetResourceStream(imageUri);
source.SetSource(s.Stream);
bitmap = new WriteableBitmap(source);
//rectangle dimensions
int width = 50, left = 115, top = 10, height = 30, cornerRadius = 5, right = 10;
var fontFamily = new FontFamily("Segoe WP");
var fontForeground = new SolidColorBrush(Colors.White);
//Textblock to show the number
TextBlock tb = new TextBlock();
tb.Text = sleeps.ToString();
tb.Foreground = new SolidColorBrush(Colors.White);
tb.FontSize = 20;
tb.Foreground = fontForeground;
tb.FontFamily = fontFamily;
tb.Margin = new Thickness(12, 4, 12, 4);
tb.Measure(new Size(width - tb.Margin.Left - tb.Margin.Right, height - tb.Margin.Top - tb.Margin.Bottom));
tb.Width = tb.ActualWidth;
tb.Height = tb.ActualHeight;
Color rectColor = Colors.Black;
//workout where to put the black rectangle behind the number
width = (int)(tb.Width + tb.Margin.Left + tb.Margin.Right);
height = (int)(tb.Height + tb.Margin.Top + tb.Margin.Bottom);
left = 173 - (right + width);
//Draw the Rectangle
bitmap.FillRectangle(left + cornerRadius, top, left + width - cornerRadius, top + height + 1, rectColor);
bitmap.FillRectangle(left, top + cornerRadius, width + left + 1, top + height - cornerRadius, rectColor);
//Draw the rounded corners
bitmap.FillEllipse(left, top + height - (cornerRadius * 2), left + (cornerRadius * 2), top + height, rectColor);
bitmap.FillEllipse(left, top, left + (cornerRadius * 2), top + (cornerRadius * 2), rectColor);
bitmap.FillEllipse(left + width - (cornerRadius * 2), top, left + width, top + (cornerRadius * 2), rectColor);
bitmap.FillEllipse(left + width - (cornerRadius * 2), top + height - (cornerRadius * 2), left + width, top + height, rectColor);
//render the TextBlock over the top
bitmap.Render(tb, new TranslateTransform { X = left + (width / 2.0) - (tb.Width / 2), Y = top + (height / 2.0) - (tb.Height / 2) });
// Invalidate the bitmap to make it actually render.
bitmap.Invalidate();
// Create our bitmap, in our selected dimension.
if (store.FileExists(newPath)) store.DeleteFile(newPath);
// Create a stream to store our file in.
var stream = store.CreateFile(tileImage);
// Save it to our stream.
bitmap.WritePNG(stream);
stream.Flush();
// Close the stream, and by that saving the file to the ISF.
stream.Close();
This works pretty well for me. I have an Id for the thing the Live Tile relates to. If it was a weather app it could be the zip code or an Id for the town for example. This needs to be used to keep the tile images from being written over each other.
To use an IsolatedStorage file as a Live Tile it needs to be in the /Shared/ShellContent folder.
The Uri that you put as the background image for the tile needs to start isostore: so it ends up like:
isostore:/Shared/ShellContent/CustomImage1.png
This will then work as the tile image:
