I have talked about how to create custom Live Tile in 《Windows Phone 實用開發技巧(17):自定義應用程序的Tile》. Today let’s dig a little bit deeper. html
What do you see in this p_w_picpath shown below ?windows
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 ?app
Yes, we can do that. All we need to do is to create a transparent png file and save it to Isolated.ide
Maybe you have already know, we can save jpg file to Iso with following code:post
WriteableBitmap bit = new WriteableBitmap(); bit.SaveJpeg(stream, 480, 800, 0, 100);
orthis
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 p_w_picpaths. Here I use the famous open souce ImageTools.spa
We can use two differernt ways to dynamic create p_w_picpaths. One way I have post here.code
//add encoder for png p_w_picpath 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:component
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:orm
public static void CreateTile(Uri p_w_picpathUri, string temperature, string timeOfDay) { var source = new BitmapImage(p_w_picpathUri) { CreateOptions = BitmapCreateOptions.IgnoreImageCache, }; string fullPath = tiledirectory + @"/" + timeOfDay + ".png"; // This is important. The p_w_picpath can't be rendered before it's loaded. source.ImageOpened += (sender, e) => { // Create our p_w_picpath 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 p_w_picpath 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, .