Windows Phone - 動態建立Tile的PNG圖像

Windows Phone - 動態建立Tile的PNG圖像

根據當麻在<[WindowsPhone] 動態製作圖片至IsolatedStorage,並更新磁貼>介紹如何動態產生Tile專用的圖像後,

讓我非常有興趣,想要進一步合入我的Appc中,因為剛好有些用戶也有建議。因此,我就來了解一下作法。

本篇將針對<[WindowsPhone] 動態製作圖片至IsolatedStorage,並更新磁貼>的內容加上補充將指定的圖像建立成

PNG檔案的方法。也許你會想說幹嘛要用*.png,其原因在於Tile的BackgroundImage設定為*.png的透明底,才能

隨著Theme的顏色來切換。所以我才會需要有建立Png的需求。

 

 

ToolStack C# PNG Writer Library

    該篇內容裡提供了重要的元素來協助將BitmapImage轉換成*.png的檔案內容。因為在WP內鍵的WriteBitmap裡,

僅支持產生*.jpg的檔案,這樣對於要產生可以隨著WP內鍵顏色主題切換時,Tile背景色會改變是無法做到的。

因此,來看一下該篇介紹的三大元素:

 

(a) WriteableBitmapExtensions

       該類別主要為WriteableBitmap的Extensions類別,擴充在使用WriteableBitmap可直接呼叫WritePNG()的方法。

關於怎麼擴充既有的類別功能可以參考<Extension Methods (C# Programming Guide)>。

 

 

(b) ToolStackPNGWriterLib系列

     b-1. PNGWriter

             負責將WriteableBitmap轉換成*.png檔案的類別,搭配PngHeader與PngChunkTypes建立*.png檔案必要的元素。

 

     b-2. PngHeader

             定義*.png檔案的標題,包括:Width、Height、BitDepath、ColorType、CompressionMethod、FilterMethod與InterlaceMethod。

 

     b-3. PngChunkTypes

             定義一個合法的*.png檔案需要指定的類型,相關PNG的規範可以參考<PNG (Portable Network Graphics) Specification>。

 

 

(c) ToolStackCRCLib系列

      c-1. CRC32:定義CRC32的數據值做為計算之用;

      c-2. Adler32:定義 Adler32 CRC 的數據值做為計算之用;

 

大致上了解其三個類別的觀念就好,最重要的類別在於Extension method的WriteableBitmapExtensions。往下便透過範例來加以說明。

 

 

〉範例說明

(1) 先透過VS 2012的NuGet取得「WriteableBitmapEx」,即會得到如下三個檔案

     image

 

(2) 定義要做為Tile的模版

     此處我使用的是UserControl的方式,把要建立的模版定義好,並且開發屬性讓產生者可以使用。圖示如下:

    image

     對應的xaml指定如下:

<UserControl x:Class="DynaBuildTile.TileTemplate.Tile_Sample"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="159" d:DesignWidth="159">
 
    <Grid x:Name="LayoutRoot">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="40*" />
            <ColumnDefinition Width="60*" />
        </Grid.ColumnDefinitions>
        <StackPanel Grid.Column="0" HorizontalAlignment="Center"  VerticalAlignment="Center">
            <!-- 定義放置City的TextBlock -->
            <TextBlock x:Name="tblCity" Text="高雄" TextWrapping="Wrap"
                       Style="{StaticResource PhoneTextExtraLargeStyle}" />
        </StackPanel>
        <StackPanel Grid.Column="1"  HorizontalAlignment="Center" VerticalAlignment="Center"
                    Margin="0,0,0,10">
            <!-- 定義放置Bus Name的TextBlock -->
            <TextBlock x:Name="tblNumber" Text="紅22-台北港小" TextWrapping="Wrap"
                       FontWeight="Bold" FontSize="26" FontFamily="Segoe WP Black"
                       />
        </StackPanel>
    </Grid>
</UserControl>

 

(3) 在MainPage.xaml撰寫建立Tile的邏輯

      在撰寫邏輯時,有一個要特別注意的地方:「要能夠讓WriteableBitmap建立的圖像,均需要顯示於Page之中」,

但是UserControld加到既有的畫面,將會造成排版的問題,而且我不想被用戶看到有這個東西,那該怎麼辦呢?

這其中有一個重點:「設定該UserControl的Margin Top為負的最大值,再加入畫面」(非常感謝當麻的指導)。那往下快來看看怎麼做吧。

 

3.1. 先在「Shared\SheelContent」建立一個目錄,放置所建立的*.png檔(這是選用的,並不一定要做這個動作);

private async Task<bool> BuildFolder()
{
    StorageFolder tFolder = null;
    StorageFolder tSTileFolder = null;
    try
    {
        // 取得shared/sharedcontent目錄,並且試著取得指定目錄sencondTiles
         tFolder = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFolderAsync("Shared");
        tFolder = await tFolder.GetFolderAsync("ShellContent");
        tSTileFolder = await tFolder.GetFolderAsync("secondTiles");
    }
    catch (Exception ex) {}
 
    if (tSTileFolder == null)
    {
        try
        {
            //代表不存在,建立一個新的Folder
            tSTileFolder = await tFolder.CreateFolderAsync("secondTiles");
        }
        catch (Exception ex) {}
    }
    return true;
}

 

3.2. 建立UserControl並且加入至畫面中;

private async void btnCreateTile_Click(object sender, RoutedEventArgs e)
{
    //建立指定的目錄
    await BuildFolder();
    //Tile範例1
    gTileSample = new Tile_Sample();
    gTileSample.tblCity.Text = "台北";
    gTileSample.tblNumber.Text = "787經瑞芳工業區";
    gTileSample.Height = 159;
    gTileSample.Width = 159;
    //定義該元件需要出現在非用戶可視的範圍
    gTileSample.Margin = new Thickness(0, -1000, 0, 0);
    LayoutRoot.Children.Add(gTileSample);
}

 

3.3. 將該UserControl利用WriteableBitmap寫成*.png檔至Shared\ShellContent\secondTiles,並且建立Tile至畫面中;

private Tile_Sample gTileSample = null;
private string gFileName = "DyncTile";
private string gRelatviePath = @"\Shared\ShellContent\secondTiles\";
private string gRelativePath2 = @"isostore:/Shared/ShellContent/secondTiles/";
 
private void AddTile() 
{
    string tFilePath = string.format("{0}{1}.png", gRelatviePath, gFileName);
    WriteableBitmap wb = new WriteableBitmap(gTileSample, null);
 
    var isolatedStorage = IsolatedStorageFile.GetUserStoreForApplication();
    //如果檔案存在,先刪除
    if (isolatedStorage.FileExists(fileName))
        isolatedStorage.DeleteFile(fileName);
 
    //建立檔案
     var fileStream = isolatedStorage.CreateFile(fileName);
    //將WriteableBitmap寫入至PNG
    wb.WritePNG(fileStream); 
    fileStream.Close();
 
    //建立Tile至Start畫面
     StandardTileData tTileData = new StandardTileData
    {
      //指定BackgroundImage需要用Absolute,所以用isostore
       BackgroundImage = new Uri(gRelatviePath2 + gFileName + ".png", UriKind.Absolute),
       Title = "Sample"
    };
   ShellTile.Create(new Uri("/MainPage.xaml?Key=pou&id=" + gFileName, UriKind.Relative), tTileData);
}

 

4. 執行結果:

   wp_ss_20131008_0002

 

[範例程式]

 

[注意]

a. ShellTile的BackgroundImage或BackBackgroundImage,需要指定在「Shared\ShellContent」裡的圖像;

b. 要能夠讓WriteableBitmap建立的圖像,均需要顯示於Page之中;

======

以上是簡單改寫了當麻的範例所補充的內容。當然如果你使用的Tile不需要產生透明背景,那就不用太在意了,大家可以參考看看,作為筆記。

 

References

WriteableBitmapEx & save PNG (transparent picture)

Silverlight SharpZipLib

ToolStack C# PNG Writer Library (重要)

[WindowsPhone] 動態製作圖片至IsolatedStorage,並更新磁貼

Windows Phone 7 – Screenshot你的WP7 App

Windows Phone 7 - 學習新的Secondary Tile與Application Tile

Pre-defined system styles and resources in Windows Phone 7

Centering TextBlock text inside border element

Is there any way to save an image object as png to keep the transparent colour

Saving WriteableBitmap to PNG

Saving a bitmap to png and retrieving back - Windows Phone 8

Extension Methods (C# Programming Guide) (重要觀念)

How to: Implement and Call a Custom Extension Method (C# Programming Guide)

 

Dotblogs 的標籤: