I have talked about how to create custom Live Tile in 《Windows Phone 实用开发技巧(17):自定义应用程序的Tile》. Today let’s dig a little bit deeper.
What do you see in this image shown below ?
Do you see the same tile with different background called accent color in windows phone . So how can we create such tile . One simplest way is we replace ApplicationIcon.png with a transparent png file. But as we know it is just main tile of our app. Can we create own tile since we can pin what we want to start ?
Yes, we can do that. All we need to do is to create a transparent png file and save it to Isolated.
Maybe you have already know, we can save jpg file to Iso with following code:
WriteableBitmap bit = new WriteableBitmap(); bit.SaveJpeg(stream, 480, 800, 0, 100);
or
Extensions.SaveJpeg(WriteableBitmap, stream, 480, 800, 0, 100);
But jpg can not be transparent. So we need some extra library to help us create transparent png images. Here I use the famous open souce ImageTools.
We can use two differernt ways to dynamic create images. One way I have post here.
//add encoder for png image Encoders.AddEncoder<PngEncoder>(); StandardTileData std = new StandardTileData { BackgroundImage = new Uri(CreateBackground()), Title = "Tile Test", BackTitle = "Secondary", BackBackgroundImage = new Uri(CreateBackground()) }; ShellTile.Create(new Uri("/MainPage.xaml?type=1", UriKind.Relative), std); sw.Stop(); Debug.WriteLine("Tranditonal method took time :" + sw.ElapsedMilliseconds);
Here is CreateBackground method looks like:
public static string CreateBackground() { Grid grid = new Grid { Background = new ImageBrush { ImageSource = new BitmapImage { UriSource = new Uri("/mangTile;component/Images/1.png", UriKind.Relative), CreateOptions = BitmapCreateOptions.IgnoreImageCache } }, Width = 173, Height = 173 }; TextBlock tb = new TextBlock { Text = "Hello world", Foreground = new SolidColorBrush(Colors.Red), FontSize = 32, }; grid.Children.Add(tb); grid.Arrange(new Rect(0d, 0d, 173, 173)); WriteableBitmap wbmp = new WriteableBitmap(grid, null); ExtendedImage extendImage = wbmp.ToImage(); using (var store = IsolatedStorageFile.GetUserStoreForApplication()) { if (!store.DirectoryExists(tiledirectory)) { store.CreateDirectory(tiledirectory); } using (var stream = store.OpenFile(fullPath, System.IO.FileMode.OpenOrCreate)) { extendImage.WriteToStream(stream, fullPath); } } return "isostore:/" + fullPath; }And as we run it we can see what shown below:
Another way is just render it within ImageOpened event:
public static void CreateTile(Uri imageUri, string temperature, string timeOfDay) { var source = new BitmapImage(imageUri) { CreateOptions = BitmapCreateOptions.IgnoreImageCache, }; string fullPath = tiledirectory + @"/" + timeOfDay + ".png"; // This is important. The image can't be rendered before it's loaded. source.ImageOpened += (sender, e) => { // Create our image as a control, so it can be rendered to the WriteableBitmap. var cloudImage = new Image { Source = source, Width = 173, Height = 173 }; // TextBlock for the time of the day. TextBlock tbTemperature = new TextBlock { Text = temperature + '°', FontSize = 36, Foreground = new SolidColorBrush(Colors.White), FontFamily = new FontFamily("Segoe WP"), }; using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication()) { if (!store.DirectoryExists(tiledirectory)) { store.CreateDirectory(tiledirectory); } var bitmap = new WriteableBitmap(173, 173); // Render our background. Remember the renders are in the same order as XAML, // so whatever is rendered first, is rendered behind the next element. // Render our cloud image bitmap.Render(cloudImage, new TranslateTransform()); // Render the temperature text. bitmap.Render(tbTemperature, new TranslateTransform() { X = 124, Y = 63 }); bitmap.Invalidate(); ExtendedImage extendImage = bitmap.ToImage(); using (var stream = store.OpenFile(fullPath, System.IO.FileMode.OpenOrCreate)) { extendImage.WriteToStream(stream, fullPath); } StandardTileData std = new StandardTileData { BackgroundImage = new Uri("isostore:/" + fullPath), Title = "Tile Test22", BackTitle = "Secondary", BackBackgroundImage = new Uri("isostore:/" + fullPath) }; ShellTile.Create(new Uri("/MainPage.xaml?type=2", UriKind.Relative), std); } }; }
I have a test on it(Conculsion is prefer to use second way as it’s faster and more stable! )
Tranditonal took 239 ms, Image size 6.11kb
Render took 10 ms, Image size 5.24kb.
You can find demo source code here. Hope that helps, .