かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

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

ということで

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