自動轉換生成 iOS 與 Android 使用的各種不同尺寸之應用程式 Icon
當使用 Prism Template Pack 專案樣板產生一個 Xamarin.Forms 專案後,並且開發完成相關需求程式碼,此時,將會發現到,不論 iOS 或者 Android 平台下的該應用程式圖示,並不是程式設計師所想要到,那麼,要怎麼進行設定與變更了。
了解更多關於 [Xamarin.Android] 的使用方式
了解更多關於 [Xamarin.iOS] 的使用方式
了解更多關於 [Xamarin.Forms] 的使用方式
了解更多關於 [Hello, Android:快速入門] 的使用方式
了解更多關於 [Hello, iOS – 快速入門] 的使用方式
了解更多關於 [Xamarin.Forms 快速入門] 的使用方式
不論在 iOS 或者 Android 平台下,對於應用程式圖示 Application Icon,需要提供不同縮放比例大小的圖片檔案,而且,在不同平台下,對於這些圖片資源檔案的命名規則也都不盡相同,在 iOS 平台下,每個圖片都會放置在 Resource 的目錄下,並且每個圖片都可以有三種尺寸,正常大小、放大兩倍與放大三倍,不同放大倍率的圖片,則需要該圖片檔案的檔名(在 .副檔案名稱前)後,加入 @1x, @2x, @3x,另外,對於正常大小的 @1x 這個文字,是可以省略的。
而對於 Android 平台下,不同放大倍率的圖片,其圖片檔案名稱都是相同的,不過,不同放大倍率的圖片,需要放置到 Resources 目錄下的不同目錄下,在 Android 平台下,共有這些放大倍率可以選擇:
附加名稱 | DPI | 放大倍率 |
---|---|---|
mdpi | 160 | 1× |
hdpi | 240 | 1.5× |
xhdpi | 320 | 2× |
xxhdpi | 480 | 3× |
xxxhdpi | 640 | 4× |
對於應用程式圖示 Application Icon ,需要在不同放大倍率代表附加名稱前面,要加上 mipmap- 這樣的文字,例如:mipmap-mdpi,對於一般的圖片資源,需要在不同放大倍率的代表附加名稱前面,要加上 drawable 這樣的文字,例如: drawable-xhdpi。
因此,當視覺設計師完成該應用程式的圖片檔案設計之後,需要請視覺設計師產出這些不同平台需要用到的放大倍率圖片,以及根據該行動平台的規範,將不同倍率的圖片,設定為適當的檔案名稱,或者要放大適當的目錄下。
為了要解決這些問題,所以設計了 AppIconBuilder 這個專案,該專案是由兩個類別來組成 iOSImageDefinition / AndroidImageDefinition ,而完整的原始碼可以從從 Github 取得
namespace AppIconBuilder
{
public class iOSImageDefinition
{
public List<iOSImageItem> Images { get; set; }
public Info info { get; set; }
public void CalculateSize()
{
foreach (var item in Images)
{
item.CalculateSize();
}
}
public void GenerateIcons(string mainPath)
{
if (Directory.Exists(mainPath) == false)
{
Directory.CreateDirectory(mainPath);
}
foreach (var item in Images)
{
using (Image<Rgba32> image = Image.Load("icon.png"))
{
image.Mutate(x => x
.Resize((int)item.Width, (int)item.Height));
string filename = Path.Combine(mainPath, item.Filename);
image.Save(filename); // Automatic encoder selected based on extension.
}
}
}
}
public class iOSImageItem
{
public string Idiom { get; set; }
public string Size { get; set; }
public string Scale { get; set; }
public string Filename { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public void CalculateSize()
{
var fooSize = Convert.ToDouble(Size.Split('x')[0]);
var fooScale = Convert.ToInt32(Scale.Replace("x", ""));
Width = fooSize * fooScale;
Height = fooSize * fooScale;
}
}
public class Info
{
public int Version { get; set; }
public string Author { get; set; }
}
}
namespace AppIconBuilder
{
public class AndroidImageDefinition
{
public List<AndroidImageItem> Images { get; set; }
public void Initialization()
{
Images = new List<AndroidImageItem>();
Images.Add(new AndroidImageItem()
{
Path = "mipmap-hdpi",
Filename = "ic_launcher.png",
Width = 72,
Height = 72,
});
Images.Add(new AndroidImageItem()
{
Path = "mipmap-ldpi",
Filename = "ic_launcher.png",
Width = 36,
Height = 36,
});
Images.Add(new AndroidImageItem()
{
Path = "mipmap-mdpi",
Filename = "ic_launcher.png",
Width = 48,
Height = 48,
});
Images.Add(new AndroidImageItem()
{
Path = "mipmap-xhdpi",
Filename = "ic_launcher.png",
Width = 96,
Height = 96,
});
Images.Add(new AndroidImageItem()
{
Path = "mipmap-xxhdpi",
Filename = "ic_launcher.png",
Width = 144,
Height = 144,
});
Images.Add(new AndroidImageItem()
{
Path = "mipmap-xxxhdpi",
Filename = "ic_launcher.png",
Width = 192,
Height = 192,
});
}
public void ChangeRole()
{
foreach (var item in Images)
{
item.Path = item.Path.Replace("mipmap", "drawable");
item.Filename = item.Filename.Replace("ic_launcher", "icon");
}
}
public void GenerateIcons(string mainPath)
{
foreach (var item in Images)
{
string path = Path.Combine(mainPath, item.Path);
if (Directory.Exists(path) == false)
{
Directory.CreateDirectory(path);
}
using (Image<Rgba32> image = Image.Load("icon.png"))
{
image.Mutate(x => x
.Resize((int)item.Width, (int)item.Height));
string filename = Path.Combine(path, item.Filename);
image.Save(filename); // Automatic encoder selected based on extension.
}
}
}
}
public class AndroidImageItem
{
public string Filename { get; set; }
public string Path { get; set; }
public double Width { get; set; }
public double Height { get; set; }
}
}
底下為這兩個類別的使用方式
namespace AppIconBuilder
{
class Program
{
// http://iconhandbook.co.uk/reference/chart/
static async Task Main(string[] args)
{
string mainPath = "iOS";
var fooContents = await File.ReadAllTextAsync("Contents.json");
iOSImageDefinition imageDefinition = JsonConvert.DeserializeObject<iOSImageDefinition>(fooContents);
imageDefinition.CalculateSize();
imageDefinition.GenerateIcons(mainPath);
mainPath = "Android_Launcher";
AndroidImageDefinition androidImageDefinition = new AndroidImageDefinition();
androidImageDefinition.Initialization();
androidImageDefinition.GenerateIcons(mainPath);
mainPath = "Android_Resource";
androidImageDefinition.ChangeRole();
androidImageDefinition.GenerateIcons(mainPath);
Console.WriteLine("Press any key for continuing...");
Console.ReadKey();
}
}
}