かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

Windows 8のストアアプリをとりあえずWindows 8.1対応する方法(間違ってた)

訂正

Windows 8.1にリターゲットするだけで、それなりに対応してくれました。 http://www.atmarkit.co.jp/ait/articles/1308/29/news069.html

以下の間違ってる内容は、標準の挙動じゃ満足できない場合にのみやるのがいいかと…。例えば、縦長をデフォルトだとポートレイトになるのをFilledにしたいとか。

以下間違ってる内容

Windows ストア アプリのデフォルトのテンプレートに沿って作ってる人は、大体LayoutAwarePageを継承して作成しているはずです。このLayoutAwarePageには、Windows 8の頃は状況に応じて適切なApplicationViewStateを使ってVisualStateを変更してくれるのですが、こいつが8.1でまさかの非推奨。スナップなんて無かった状態になってしまいます。

f:id:okazuki:20130910220354p:plain

こいつをどうにかする方法として、LayoutAwarePageを使ってる人が一番簡単にWindows 8.1上でもそれなりに動くようにする方法をちょっと考えてみました。

LayoutAwarePageを見てみる

LayoutAwarePageでは、Windowのサイズ変更などのタイミングでVisualStateを変更しています。この時VisualStateの名前を決定しているメソッドが、LayoutAwarePageのDetermineVisualStateになります。

/// <summary>
/// <see cref="ApplicationViewState"/> 値を、ページ内の表示状態管理で使用できる文字列に
/// 変換します。既定の実装では列挙値の名前を使用します。
/// サブクラスでこのメソッドをオーバーライドして、使用されているマップ スキームを制御する場合があります。
/// </summary>
/// <param name="viewState">表示状態が必要なビューステート。</param>
/// <returns><see cref="VisualStateManager"/> の実行に使用される
/// 表示状態の名前</returns>
/// <seealso cref="InvalidateVisualState"/>
protected virtual string DetermineVisualState(ApplicationViewState viewState)
{
    return viewState.ToString();
}

ここを、単純にApplicationViewStateを文字列化しているのをやめて、表示されてる状態に応じて適切なVisualStateを返してやることで、Windows 8.1でもそれなりに動くようになります。例えば、以下のように書き換えてみるといいかも??

/// <summary>
/// <see cref="ApplicationViewState"/> 値を、ページ内の表示状態管理で使用できる文字列に
/// 変換します。既定の実装では列挙値の名前を使用します。
/// サブクラスでこのメソッドをオーバーライドして、使用されているマップ スキームを制御する場合があります。
/// </summary>
/// <param name="viewState">表示状態が必要なビューステート。</param>
/// <returns><see cref="VisualStateManager"/> の実行に使用される
/// 表示状態の名前</returns>
/// <seealso cref="InvalidateVisualState"/>
protected virtual string DetermineVisualState(ApplicationViewState viewState)
{
    var view = ApplicationView.GetForCurrentView();
    if (view.IsFullScreen)
    {
        return  view.Orientation == ApplicationViewOrientation.Portrait ?
            "FullScreenPortrait":
            "FullScreenLandscape";
    }

    var w = Window.Current;
    var width = w.Bounds.Width;
    return width == 320 ? "Snapped" : "Filled";
}

そして、Windows 8.1では、デフォルトでアプリの幅は500pxになってるので折角対応しているスナップ表示がいかせないので、appxmanifestを開いて最小幅を320pxにします。

f:id:okazuki:20130910221255p:plain

この変更を、Windows 8 ストア アプリ開発入門のサンプルプログラムのRSSリーダーに適用するとこんな感じになります。

全画面表示は当然OK

f:id:okazuki:20130910221429p:plain

縦にしてもOK

f:id:okazuki:20130910221500p:plain

中途半端な大きさもOK

f:id:okazuki:20130910221626p:plain

スナップ?もOK

f:id:okazuki:20130910221348p:plain

ということで

とりあえずの対応としては十分っぽい。