セカンダリ・タイルを活用するには?[Win 8]WinRT/Metro TIPS

スタート画面に表示されるアプリのタイルは、そのアプリにより増やせる。アプリで2つ目以降のタイルは「セカンダリ・タイル」と呼ばれる。その作成方法を説明する。

» 2013年02月07日 12時25分 公開
[山本康彦BluewaterSoft]
WinRT/Metro TIPS
業務アプリInsider/Insider.NET

powered by Insider.NET

「WinRT/Metro TIPS」のインデックス

連載目次

 スタート画面に表示されるアプリのタイルは、そのアプリにより増やすことができる。アプリで2つ目以降のタイルを「セカンダリ・タイル」と呼ぶ。そして、セカンダリ・タイルからアプリの特定のページや検索結果などが直接開くようなプログラムを作ることが可能だ。エンド・ユーザー(以降、ユーザー)は「スタート画面にピン留めする*1」コマンドで、この機能を利用できる。本稿では、そのようなセカンダリ・タイルを活用する方法を説明する。本稿のサンプルは「Windows Store app samples:MetroTips #23」からダウンロードできる。

*1 英語のアプリでの表記は、「Pin to Start」/「Unpin from Start」。日本語のアプリでは「スタート画面にピン留めする」/「スタート画面からピン留めを外す」が推奨されているが、そのような長い文字列をコマンド・ボタンの下に表示すると改行されてしまうため、「ピン留めする」/「ピン留め解除」などと略記しているアプリもある。


事前準備

 Windows 8(以降、Win8)向けのWindowsストア・アプリを開発するには、Win 8とVisual Studio 2012(以降、VS 2012)が必要である。これらを準備するには、第1回のTIPSを参考にしてほしい。本稿では64bit版Win 8 ProとVS 2012 Express for Windows 8を使用している。

セカンダリ・タイルを作成するには?

 SecondaryTileクラス(Windows.UI.StartScreen名前空間)のオブジェクトを作り、ユーザーにピン留めの許可を求めるリクエストを発行すればよい。

 まず、SecondaryTileクラスをインスタンス化し、必要なパラメータをセットする。次に挙げるのは必須のパラメータ(厳密にはSecondaryTileクラスのプロパティ)だ。

【必須のパラメータ】

  • TileId:セカンダリ・タイルに付ける一意のID
  • ShortName:セカンダリ・タイルに表示する短い名前
  • DisplayName:表示名
  • Arguments:引数文字列(セカンダリ・タイルからの起動時にアプリに渡される)
  • Logo:正方形タイル画像のURI

 そうしたらSecondaryTileクラスのRequestCreateForSelectionAsyncメソッドを呼び出す。コードとしてはこれだけである(次のコード)。

private async Task<bool> CreateSecondaryTile(Rect buttonArea)
{
  var secondaryTile = new Windows.UI.StartScreen.SecondaryTile() {
    TileId = "Test",  // 【必須】タイルを識別するID。削除時にも使う
    ShortName = "TIP#23 2nd",  // 【必須】タイルに表示される短い名前
    DisplayName = "WinRT/Metro TIPS #23 - 2nd tile", // 【必須】アプリの長い名前
    Arguments = "試験です", // 【必須】起動時に渡される引数
    TileOptions   // 省略可
      = Windows.UI.StartScreen.TileOptions.ShowNameOnLogo
        | Windows.UI.StartScreen.TileOptions.ShowNameOnWideLogo,
    Logo = new Uri("ms-appx:///Assets/Logo.png"),  // 【必須】
    WideLogo = new Uri("ms-appx:///Assets/WideLogo.png"), // 【オプション】
    // ※既定のワイド・ロゴがなくても、セカンダリにワイド・ロゴが設定できる
    BackgroundColor
      = Windows.UI.Color.FromArgb(0xff, 0x0, 0xA2, 0xE8), // 【オプション】
    ForegroundText
      = Windows.UI.StartScreen.ForegroundText.Light,  // 【オプション】
  };
  bool isPinned
    = await secondaryTile.RequestCreateForSelectionAsync(
                    buttonArea, Windows.UI.Popups.Placement.Above);
  return isPinned;
}

Private Async Function CreateSecondaryTile(buttonArea As Rect) _
                         As Task(Of Boolean)
  Dim secondaryTile = New Windows.UI.StartScreen.SecondaryTile()
  With secondaryTile
    .TileId = "Test"  ' 【必須】タイルを識別するID。削除時にも使う。
    .ShortName = "TIP#23 2nd VB" ' 【必須】タイルに表示される短い名前。
    .DisplayName = "WinRT/Metro TIPS #23 - 2nd tile (VB)"  ' 【必須】アプリの長い名前。
    .Arguments = "試験です" ' 【必須】起動時に渡される引数。
    .TileOptions _
      = Windows.UI.StartScreen.TileOptions.ShowNameOnLogo _
        Or Windows.UI.StartScreen.TileOptions.ShowNameOnWideLogo ' 省略可
    .Logo = New Uri("ms-appx:///Assets/Logo.png") ' 【必須】
    .WideLogo = New Uri("ms-appx:///Assets/WideLogo.png") ' 【オプション】
    ' ※既定のワイド・ロゴがなくても、セカンダリにワイド・ロゴが設定できる
    .BackgroundColor _
        = Windows.UI.Color.FromArgb(&HFF, &H0, &HA2, &HE8)  ' 【オプション】
    .ForegroundText _
        = Windows.UI.StartScreen.ForegroundText.Light ' 【オプション】
  End With
  Dim IsPinned As Boolean _
      = Await secondaryTile.RequestCreateForSelectionAsync( _
                      buttonArea, Windows.UI.Popups.Placement.Above)
  Return IsPinned
End Function

セカンダリ・タイルを作成するメソッド(上:C#、下:VB)

 このメソッドのRect型の引数「buttonArea」には、タップされたコマンド・ボタンの場所を渡す(場所を取得するコードは後述)。そしてメソッドを呼び出すと、コマンド・ボタンのすぐ上に次の画像のようなポップアップが表示される。

セカンダリ・タイルの作成許可をユーザーに求めるポップアップ
コードで指定したワイド・ロゴと短い名前が表示されている。

 ここでユーザーが[スタート画面にピン留めする]をタップすると、実際にセカンダリ・タイルが作成され、RequestCreateForSelectionAsyncメソッドの戻り値はtrueになる。タップしなければ、セカンダリ・タイルは作成されず、メソッドはfalseを返す。また、ユーザーはこのポップアップで、タイルに表示される短い名前を自由に変更できる。

セカンダリ・タイルを削除するには?

 ユーザーはスタート画面でいつでもセカンダリ・タイルを削除できる。コードから削除するには、ユーザーにピン留め解除の許可を求めるリクエストを発行すればよい。

 それは次のようなメソッドになる。削除対象のセカンダリ・タイルを識別するためにTileIdを使う。

private async Task<bool> RemoveSecondaryTile(Rect buttonArea)
{
  var secondaryTile
    = new Windows.UI.StartScreen.SecondaryTile("Test"); // 引数はTileId
  bool isUnpinned
    = await secondaryTile.RequestDeleteForSelectionAsync(
                  buttonArea, Windows.UI.Popups.Placement.Above);
  return isUnpinned;
}

Private Async Function RemoveSecondaryTile(buttonArea As Rect) _
                         As Task(Of Boolean)
  Dim secondaryTile _
      = New Windows.UI.StartScreen.SecondaryTile("Test") ' 引数はTileId
  Dim isUnpinned As Boolean _
      = Await secondaryTile.RequestDeleteForSelectionAsync( _
                    buttonArea, Windows.UI.Popups.Placement.Above)
  Return isUnpinned
End Function

セカンダリ・タイルを削除するメソッド(上:C#、下:VB)

 メソッドの引数には、前と同様にタップされたコマンド・ボタンの場所を渡す。メソッドを呼び出すと、画面には次の画像のようなポップアップが表示される。

セカンダリ・タイルの削除許可をユーザーに求めるポップアップ

 ここでユーザーが「スタート画面からピン留めを外す」をタップすると、実際にセカンダリ・タイルが削除されメソッドの戻り値はtrueになる。そうでなければ、削除されず戻り値はfalseになる。

 なお、存在しないTileIdを使ってRequestDeleteForSelectionAsyncメソッドを呼び出してもエラーにはならず、ポップアップも表示されることなく直ちにfalseが返ってくる。

「スタート画面にピン留め」コマンドを実装するには?

 アプリ・バーのコマンド・ボタンで上記のメソッドを呼び出すようにすればよい。

 セカンダリ・タイルを作成・削除するUIは、「MSDN:セカンダリ タイルのガイドラインとチェック リスト」によると、アプリ・バーに「スタート画面にピン留め」コマンドとして実装するように要請されている。また、セカンダリ・タイル表示中には、同じボタンが「スタート画面からピン留めを外す」に変わるようにしなければならない。

 コマンド・ボタンを切り替える方法はいくつかあるが、ここでは2つ配置しておいて片方を隠すようにしてみよう。まずは(次の画像とコードのように)VS 2012のXAMLデザイナでアプリ・バーとコマンド・ボタンをデザインする。

アプリ・バーとコマンド・ボタンのデザイン(XAMLデザイナーの一部)

<Button x:Name="buttonPin" Click="buttonPinClicked"
        Style="{StaticResource PinAppBarButtonStyle}"
        AutomationProperties.Name="ピン留めする" />
<Button x:Name="buttonUnpin" Click="buttonUnpinClicked"
        Style="{StaticResource UnPinAppBarButtonStyle}"
        AutomationProperties.Name="ピン留め解除" />

コマンド・ボタン部分のコードの抜粋(XAML)

 なお、コマンド・ボタンに適用した2つのスタイル(=「PinAppBarButtonStyle」と「UnPinAppBarButtonStyle」)は、「StandardStyles.xaml」ファイルにコメントとして記述されているので、コメントを外して使う。

 次に、コマンド・ボタンの表示を切り替えるメソッドを記述する。

private void ToggleAppBarButton(bool isPinned)
{
  if (isPinned)
  {
    buttonPin.Visibility = Visibility.Collapsed;
    buttonUnpin.Visibility = Visibility.Visible;
  }
  else
  {
    buttonPin.Visibility = Visibility.Visible;
    buttonUnpin.Visibility = Visibility.Collapsed;
  }
}

Private Sub ToggleAppBarButton(isPinned As Boolean)
  If (isPinned) Then
    buttonPin.Visibility = Visibility.Collapsed
    buttonUnpin.Visibility = Visibility.Visible
  Else
    buttonPin.Visibility = Visibility.Visible
    buttonUnpin.Visibility = Visibility.Collapsed
  End If
End Sub

コマンド・ボタンの表示を切り替えるメソッド(上:C#、下:VB)

 画面が表示されたときに、このメソッドを呼び出して片方のボタンを隠す。ページのLoadStateメソッドに次のコードを追加する。

ToggleAppBarButton(IsPinned("Test"));

ToggleAppBarButton(IsPinned("Test"))

画面表示時にコマンド・ボタンの表示を設定するコード(上:C#、下:VB)
LoadStateメソッドに追加する。なお、IsPinnedメソッドは次項で説明する。

 最後に、コマンド・ボタンがタップされたときのイベント・ハンドラを実装する(次のコード)。

private async void buttonPinClicked(object sender, RoutedEventArgs e)
{
  pageRoot.BottomAppBar.IsSticky = true;

  bool isPinned =
    await CreateSecondaryTile(GetElementRect((FrameworkElement)sender));
  ToggleAppBarButton(isPinned);

  pageRoot.BottomAppBar.IsSticky = false;
}

Private Async Sub buttonPinClicked(sender As Object, e As RoutedEventArgs)
  pageRoot.BottomAppBar.IsSticky = True

  Dim isPinned As Boolean _
    = Await CreateSecondaryTile( _
              GetElementRect(DirectCast(sender, FrameworkElement)))
  ToggleAppBarButton(isPinned)

  pageRoot.BottomAppBar.IsSticky = False
End Sub

セカンダリ・タイルを作成するイベント・ハンドラ(上:C#、下:VB)
コード中のGetElementRectメソッドは後述する。

private async void buttonUnpinClicked(object sender, RoutedEventArgs e)
{
  pageRoot.BottomAppBar.IsSticky = true;

  bool isUnpinned
    = await RemoveSecondaryTile(GetElementRect((FrameworkElement)sender));
  ToggleAppBarButton(!isUnpinned);

  pageRoot.BottomAppBar.IsSticky = false;
}

Private Async Sub buttonUnpinClicked(sender As Object, e As RoutedEventArgs)
  pageRoot.BottomAppBar.IsSticky = True

  Dim isUnpinned As Boolean _
    = Await RemoveSecondaryTile( _
              GetElementRect(DirectCast(sender, FrameworkElement)))
  ToggleAppBarButton(Not isUnpinned)

  pageRoot.BottomAppBar.IsSticky = False
End Sub

セカンダリ・タイルを削除するイベント・ハンドラ(上:C#、下:VB)
コード中のGetElementRectメソッドは次に示してある。

public static Rect GetElementRect(FrameworkElement element)
{
  GeneralTransform buttonTransform = element.TransformToVisual(null);
  Point point = buttonTransform.TransformPoint(new Point());
  return new Rect(point, new Size(element.ActualWidth, element.ActualHeight));
}

Public Shared Function GetElementRect(element As FrameworkElement) As Rect
  Dim buttonTransform As GeneralTransform = element.TransformToVisual(Nothing)
  Dim point As Point = buttonTransform.TransformPoint(New Point())
  Return New Rect(point, New Size(element.ActualWidth, element.ActualHeight))
End Function

ボタンの場所を取得するGetElementRectメソッド(上:C#、下:VB)
引数に渡されたUIオブジェクトの輪郭を包む矩形を取得して返している。

 上記のコードでは、実際にセカンダリ・タイルが作成/削除できたかどうかの結果を使って、コマンド・ボタンの表示を再設定している。また、ユーザーに問い合わせるポップアップが出ている間にアプリ・バーが閉じてしまわないように、アプリ・バーのIsStickyプロパティをコントロールしている。

現在のページが「ピン留め」されているかどうかを調べるには?

 TileIdを使って調べればよい。

 現在のページをこれから「ピン留め」するとしたらどんなTileIdになるかは算出できるはずだ。それと同じTileIdを持ったセカンダリ・タイルがすでに存在するかどうかは、次のコードで調べることができる。

private bool IsPinned(string tileId)
{
  return Windows.UI.StartScreen.SecondaryTile.Exists(tileId);
}

Private Shared Function IsPinned(tileId As String) As Boolean
  Return Windows.UI.StartScreen.SecondaryTile.Exists(tileId)
End Function

指定したセカンダリ・タイルの存在を調べるメソッド(上:C#、下:VB)

 このメソッドは、前述した「画面表示時にコマンド・ボタンの表示を設定するコード」で使っている。

セカンダリ・タイルからの起動時に特定の処理を行うには?

 起動時に、セカンダリ・タイル作成時に設定したTileIdとArgumentsが渡されるので、それに応じた処理を記述すればよい。

 セカンダリ・タイルから起動された場合、AppクラスのOnLaunchedメソッドに渡されるLaunchActivatedEventArgs型の引数「args」のプロパティに、セカンダリ・タイルの情報が入っている(次の2つ)。

  • args.TileId(String型)
  • args.Arguments(String型)

 セカンダリ・タイルから起動された場合は、これら2つともに有効な文字列が入ってくる。既定のタイルから起動されたときには、Argumentsがnull(VBではNothing)になっているので区別ができる(TileIdには既定値があって、nullにならない)。

 参考までに、起動時に受け取ったargs.TileIdとargs.Argumentsを画面に表示させてみると、次の画像のようになる。

実行結果(画面の一部)
上は、既定のタイルから起動した場合で、Argumentsはnull/Nothingになっている。
下は、セカンダリ・タイルから起動した場合で、前述のコードで設定した値が入っている。

まとめ

 セカンダリ・タイルを作成/削除するコードはそれほど難しくない。ユーザーの許可を受けずに作成/削除できない点には注意が必要かもしれない。また、本稿では触れなかったが、セカンダリ・タイルもライブ・タイルにできる。

 難しいのは、TileIdの生成の仕方やArgumentsに設定する文字列の決め方だ。この2つだけで起動時の画面遷移と遷移先での処理をコントロールしなければならないのだから、十分な設計が必要になるだろう。

 詳しくは、次のドキュメントを参考にしてほしい。

「WinRT/Metro TIPS」のインデックス

WinRT/Metro TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。