WindowsアプリとWindows Phoneアプリで共通のリソースを共有し、それぞれのアプリに固有のアプリは独自に保有するための方法を解説する。
powered by Insider.NET
ユニバーサルプロジェクトを使ってユニバーサルWindowsアプリを開発するとき、画像ファイルや文字列リソースファイルなどのリソースも共有プロジェクトに置ける。では、WindowsストアアプリとWindows Phoneアプリで異なるリソースはどのように配置したらよいだろうか? 本稿ではその方法を解説する。なお、本稿のサンプルは「Windows Store app samples:MetroTips #76」からダウンロードできる。
ユニバーサルプロジェクトを使ってユニバーサルWindowsアプリを開発するには、以下の開発環境が必要である。本稿では、無償のVisual Studio Express 2013 for Windowsを使っている。
*1 SLAT対応ハードウェアは、Windows Phone 8.1エミュレーターの実行に必要だ。ただし未対応でも、ソースコードのビルドは可能だ。SLAT対応のチェック方法はMSDNブログの「Windows Phone SDK 8.0 ダウンロードポイント と Second Level Address Translation (SLAT) 対応PCかどうかを判定する方法」を参照。なお、SLAT対応ハードウェアであっても、VM上ではエミュレーターが動作しないことがあるのでご注意願いたい。
*2 事前には「Windows 8.1 Update 1」と呼ばれていたアップデート。スタート画面の右上に検索ボタンが(環境によっては電源ボタンも)表示されるようになるので、適用済みかどうかは簡単に見分けられる。ちなみに公式呼称は「the Windows RT 8.1, Windows 8.1, and Windows Server 2012 R2 update that is dated April, 2014」というようである。
*3 マイクロソフトのダウンロードページから誰でも入手できる。
*4 本稿に掲載した手順を試すだけなら、無償のExpressエディションで構わない。Visual Studio Express 2013 Update 2 for Windows(製品版)はマイクロソフトのページから無償で入手できる。Expressエディションはターゲットプラットフォームごとに製品が分かれていて紛らわしいが、Windowsストアアプリの開発には「for Windows」を使う(「for Windows Desktop」はデスクトップで動作するアプリ用)。
本稿では、紛らわしくない限り次の略称を用いる。
Visual Studio 2013 Update 2のRTMがリリースされたが、残念なことに本稿執筆時点ではVB用のユニバーサルプロジェクトのテンプレートがまだ含まれていない。そのため、別途公開しているサンプルコードはC#だけとした。しかし本稿の内容はコードビハインドに立ち入らないので、VB/C#に関係なくご利用いただけることと思う。
ユニバーサルプロジェクトとは、大ざっぱにいえば共有プロジェクトをマージしてビルドする仕組みだ(次の図)。画像ファイルなどのリソースファイルは、WindowsとPhoneに共通するものは共有プロジェクトに、そうでなければそれぞれのプロジェクトに配置すればよい。ただし、多少異なるものもあるので、本稿では以下の3点に分けて説明していく。
概要で述べたように、適切なプロジェクトに配置すればよい。
例として、筆者が公開しているアプリ*5のソースコードを見てもらいたい(次の画像)。フォント/HTML/音声ファイルは、WindowsとPhoneで共通に使うため、共有プロジェクトに置いている。画像ファイルは、共通に使うものだけを共有プロジェクトに置き、そうでないものはWindowsとPhoneのプロジェクトに分けて配置している。
*5 ユニバーサルWindowsアプリ「クラウディアさんタイマーVer.2」(Windows用、Phone用)。そのソースコードは、Windows Store app samples:クラウディアさんタイマー (Claudia Madobe Timer) Ver.2で公開している。
スタート画面のタイル画像について、補足しておく。
画像ファイルの解像度は、96dpiを「スケール100」(=100%)として、他の解像度のものをそれに対するパーセントで表す。WindowsとPhoneでサポートされているタイル画像の解像度と配置場所をまとめると、次の表のようになる。
スケール | Windows | Phone | 配置場所 |
---|---|---|---|
80% | ○オプション | ×非サポート | Windowsプロジェクト |
100% | ◎必須 | ○オプション | 共有プロジェクト |
120% | ×非サポート | ○オプション※ | Phoneプロジェクト |
140% | ○オプション | ○オプション | 共有プロジェクト |
160% | ×非サポート | ○オプション※ | Phoneプロジェクト |
180% | ○オプション | ○オプション※ | 共有プロジェクト |
200% | ×非サポート | ○オプション※ | Phoneプロジェクト |
220% | ×非サポート | ○オプション※ | Phoneプロジェクト |
240% | ×非サポート | ◎必須 | Phoneプロジェクト |
300% | ×非サポート | ○オプション※ | Phoneプロジェクト |
400% | ×非サポート | ○オプション※ | Phoneプロジェクト |
文字列リソース(「.resw」ファイル)の場合は、少し特殊だ。
共有プロジェクトとWindows/Phoneの各プロジェクトに、同じファイル名の文字列リソースを配置できるのだ。そして、ビルド時に、これらのファイルの内容をマージしてくれるのである。
試してみよう。VS 2013でユニバーサルプロジェクトを作り、3つのプロジェクトにそれぞれ「Strings」というフォルダーを作成し、そこに「Resources.resw」という名前で文字列リソースファイルを置く(新しい項目を追加するダイアログで[リソース ファイル (.resw)]を選ぶ。次の画像)。
それぞれの「Resources.resw」ファイルには、次の画像のような文字列リソースを定義する。
上で定義した文字列リソースを、次のようなXAMLコードで利用する。
<Border ……省略…… >
<TextBlock x:Uid="CommonString" ……省略…… />
</Border>
<Border ……省略…… >
<TextBlock x:Uid="IndividualString" ……省略…… />
</Border>
実行結果を本稿の最後に掲載しておく。
スタイル定義やテンプレート定義、あるいは文字列や色などのリソースを記述するリソースディクショナリを切り分けるには、ResourceDictionaryクラス(Windows.UI.Xaml名前空間)のMergedDictionariesプロパティを利用する。リソースディクショナリの中に、別ファイルで定義したリソースディクショナリを取り込むのだ。
例として、共有プロジェクトの「App.xaml」ファイルに定義してあるリソースディクショナリに、Windows/Phoneプロジェクトに置いたリソースディクショナリを取り込んでみよう。まず、Windows/Phoneプロジェクトに「App.Resources.xaml」というファイル名でリソースディクショナリを追加する(新しい項目を追加するダイアログで[リソース ディクショナリ]を選び、ファイル名を指定する。次の画像)。
Windowsプロジェクトの「App.Resources.xaml」ファイルには、次のコードのようにWindows専用の定義を書く。
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MetroTips076CS">
<x:String x:Key="IndividualColorTitle">Windows専用の色定義</x:String>
<SolidColorBrush x:Key="IndividualColor">Blue</SolidColorBrush>
</ResourceDictionary>
Phoneプロジェクトの「App.Resources.xaml」ファイルには、次のコードのようにPhone専用の定義を書く。
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MetroTips076CS">
<x:String x:Key="PageTitle01">リソースの切り分け</x:String>
<x:String x:Key="IndividualColorTitle">Phone専用の色定義</x:String>
<SolidColorBrush x:Key="IndividualColor">DarkRed</SolidColorBrush>
</ResourceDictionary>
そして、共有プロジェクトの「App.xaml」ファイルで、上記の「App.Resources.xaml」ファイルを取り込んで利用する(次のコード)。思い出してほしいのだが、ユニバーサルプロジェクトがビルドされるときに上記2つの「App.Resources.xaml」ファイルのうちどちらかが取り込まれるのである。
<Application
x:Class="MetroTips076CS.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MetroTips076CS">
<Application.Resources>
<ResourceDictionary>
<!-- 共通のリソース -->
……省略……
<x:String x:Key="CommonColorTitle">共通の色定義</x:String>
<SolidColorBrush x:Key="CommonColor">DarkGreen</SolidColorBrush>
……省略……
<!-- Windows/Phone個別のリソースディクショナリ -->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="App.Resources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
このマージされたリソースディクショナリを、次のようにXAMLコードで利用できる。
<Border Background="{StaticResource CommonColor}">
<TextBlock Text="{StaticResource CommonColorTitle}" />
</Border>
<Border Background="{StaticResource IndividualColor}">
<TextBlock Text="{StaticResource IndividualColorTitle}" />
</Border>
また、Phoneのプロジェクトでは、「PageTitle01」というキー名の文字列リソースが定義されているので、次のコードのように使える。
<TextBlock Text="{StaticResource PageTitle01}" ……省略…… />
以上のうち、文字列リソースファイル(.reswファイル)とリソースディクショナリの切り分け方法を実行してみた結果は、次の画像のようになる。共有プロジェクトに置いたリソースと、Windows/Phoneそれぞれのプロジェクトに置いたリソースがきちんと使われている。
WindowsとPhoneに共通するリソースは共有プロジェクトに、そうでなければそれぞれのプロジェクトに配置すればよい。ただし、文字列リソースは少し特殊でファイル名が衝突してもよい。また、リソースディクショナリは取り込むためのXAMLコードの記述が必要だ。
Copyright© Digital Advantage Corp. All Rights Reserved.