雑記 - otherwise

最近はDQ10しかやっていないダメ技術者がちまちまと綴る雑記帳

ユニバーサル Windows アプリの Windows Phone アプリケーションに於ける SystemTray の扱い

ユニバーサル Windows アプリでは Windows Phone アプリケーションの基盤が Windows Runtime に替わったため、各画面を構成するクラスも Windows Phone 8.0 (以下 WP8 と記す)までの PhoneApplicationPage (Windows.Phone.Controls) から Page (Windows.UI,Xaml.Controls) に替わっています。*1
そのため、 WP8 までの様に SystemTray (Microsoft.Phone.Shell) クラスを使用してシステムトレイへアクセスする事は出来なくなりました。
そこで、ユニバーサル Windows アプリの Windows Phone アプリ(以下 WP8.1 アプリ)でシステムトレイへアクセスする場合はどうすればよいのかを紹介しておこうと思います。

StatusBar クラス

WP8.1 アプリでは StatusBar クラス (Windows.UI.ViewManagement) を使用してシステムトレイにアクセスする事が出来ます。
※このクラスは Windows Phone 用の Windows Runtime にのみ追加されたクラスのため、ユニバーサル Windows アプリ内で本クラスを使用する場合はプラットフォーム依存コードになります。

StatusBar の使い方

SystemTray と違い、 StatusBar は XAML から直接利用する事は出来ず、 C# コードからアクセスする必要があります。

var statusBar = Windows.UI.ViewManagement.StatusBar.GetForCurrentView();

※ WP8 までの様に XAML から利用したい場合は Behavior を作りましょう。( Behavior を利用した実装例は省略します)

SystemTray と StatusBar のプロパティ比較

StatusBar クラスは SystemTray とほぼ同等に利用出来ますが、幾つかの相違があります。

StatusBar
SystemTray
SystemTray
StatusBar
背景色 BackgroundColor プロパティ BackgroundColor プロパティ
文字色 ForegroundColor プロパティ ForegroundColor プロパティ
背景の不透明度 Opacity プロパティ BackgroundOpacity プロパティ
表示制御 IsVisible プロパティ ※ ShowAsync / HideAsync メソッド
ステータスバー表示領域 (Rect) ※未サポート OcculatedRect プロパティ
プログレスインジケーターへのアクセス ProgressIndicator プロパティ ProgressIndicator プロパティ

SystemTray と比べて、 ステータスバー表示領域が取得出来る様になっています。(何に利用出来るかは詳しく調べてませんが :p )
また、大きな変更点としてステータスバー表示有無の指定がプロパティから非同期メソッドに変更された事が挙げられるかと思われます。
ViewModel からステータスバーの表示を制御する際に一手間増える感じですね。

Showing / Hiding イベントの追加

表示が切り替わる際に発生するイベントが追加されました。

Opacity (BackgroundOpacity) プロパティの設定値の解釈変更

Opacity プロパティが BackgroundOpacity プロパティに変更されたのには理由がある様です。
と云うのも、 StatusBarSystemTray の Opacity プロパティに 1 未満の数値を設定した場合、ステータスバーの下にアプリケーションのコンテンツが入り込む仕様になっています(下図左)が、 SystemTrayStatusBar の BackgroundOpacity ではこの現象は発生しません。(下図右)

※プロパティの名の通り、あくまでも "Background" (背景色)の Opacity (不透明度)を設定するプロパティに変更された様です。
WP8 まではこの現象を回避するためにコンテンツの先頭にマージンを設定する等のテクニックが広まっていましたが、 WP8.1 アプリでは変に余白が増えてしまう事になるため注意が必要です。
なお、 C# コードから以下の設定を行う事で WP8 の StatusBarSystemTray.Opacity と同様の制御にする事が出来ます。
※ステータスバーを表示しつつ ScrollViewer のスクロールを領域最上段まで行いたいケース等では必要になってくるかと思われます。

var appView = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView();
appView.SetDesiredBoundsMode(Windows.UI.ViewManagement.ApplicationViewBoundsMode.UseCoreWindow);

StatusBarProgressIndicator クラス

ProgressIndicator を管理するクラスも ProgressIndicator (Microsoft.Shell) から StatusBarProgressIndicator (Windows.UI.ViewManagement) に替わりました。

ProgressIndicator StatusBarProgressIndicator
進行状況を示す値 Value プロパティ (double) ProgressValue プロパティ (double?)
不確定パターン IsIndeterminate プロパティ (bool) ※ ProgressValue に null を設定
表示テキスト Text プロパティ (string) Text プロパティ (string)
表示制御 IsVisible プロパティ (bool) ※ ShowAsync / HideAsync メソッド

Indeterminate モードへの切替方法が大きく変わりました( bool プロパティ→値に null 設定)。
また、ステータスバー同様、表示制御が非同期メソッドになっています。
※ StatusBarProgressIndicator クラスには表示切り替え時のイベントはない様です。

*1:Windows Phone 8.1 Silverlight アプリは WP8 までと変わりません。