第2回:Xamarin.FormsとネイティブUI特集:Xamarin+Visual Studioで始めるiOS/Android/UWPアプリ開発(4/5 ページ)

» 2016年11月02日 05時00分 公開
[山本康彦BluewaterSoft/Microsoft MVP for Windows Development]

Xamarin.Formsの画面遷移の例:ハンバーガーメニュー

 Xamarin.Formsで画面の左側から出てくるメニュー(いわゆる「ハンバーガーメニュー」)を作ってみよう。そして、メニューで選択した画面に遷移させる。次の画像のような画面だ。

画面左上のハンバーガーボタンをクリック
画面左上のハンバーガーボタンをクリック
出てきたメニューで他の画面を選択
出てきたメニューで他の画面を選択
画面遷移する ハンバーガーメニューで画面遷移するアプリ(Windows 10 PC)
上: 起動されたときは、[DetailPage1](赤い画面)が見えている。
中: 画面左上のハンバーガーボタン(またはリンク)をクリック/タップすると、このように左からメニューが出てくる。
下: 左のメニューで別の画面を選択すると、このように画面遷移する。タブレットモードではないWindowsデスクトップで実行した場合、左上に[戻る]ボタンが自動的に表示される。

 このような画面を作るには、MasterDetailPageコントロールを使う。MasterDetailPageコントロールには、2つのPageコントロールを収めるセクションがある。「Master」と「Detail」だ。ただし、左から出てくるメニュー部分が「Master」で、上の画像で赤や緑の色が付いている部分が「Detail」である。

 そして、「Detail」に収めるPageコントロールとしてNavigationPageコントロールを使えば、「Detail」の中だけを画面遷移させられる。

 では、作ってみよう。以下で説明するコードの全体は、「Microsoft Developer Network > サンプル > Xamarin入門#02 HamburgerMenu」からダウンロードできる。

 "Hello, Xamarin!"アプリと同様にして、プロジェクトテンプレートに[Blank Xaml App (Xamarin.Forms Portable)]を選んでソリューションを作る。プロジェクト名は「HamburgerMenu」とする。

 まずは、「Detail」画面の中に表示する画面から作ろう。PCLプロジェクトに[Forms Xaml Page]を3つ追加する([新しい項目の追加]ダイアログで[Cross-Platform]セクションにある)。ファイル名は「DetailPage1.xaml」/「DetailPage2.xaml」/「DetailPage3.xaml」とする。「DetailPage1.xaml」ファイルは次のコードのように編集する。残りの2つも同じように、ただし、見た目で区別できるように編集しておく。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="HamburgerMenu.DetailPage1"
             Title="Hamburger Menu Page-01"
             BackgroundColor="#22ff0000"
             >
  <ContentPage.Padding>
    <OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" />
  </ContentPage.Padding>
  <!--<Label Text="{Binding MainText}" VerticalOptions="Center"
         HorizontalOptions="Center" />-->
  <Label Text="DetailPage1" VerticalOptions="Center" HorizontalOptions="Center"
         FontSize="Large"/>
</ContentPage>

「DetailPage1.xaml」ファイル(XAML)
太字の部分を追加/変更した。
「DetailPage2.xaml」/「DetailPage3.xaml」も同様に、ただし、見た目で区別できるように背景色や文字列は異なる設定にしておく。
<ContentPage.Padding>で始まる3行は、iOSで上側のスペースを調整するためのものだ。その中の<OnPlatform>要素については「.NET TIPS:Xamarin.Forms:プラットフォームに応じて画面の一部を変えるには?」を参照してほしい。

 次に、「Master」の中に表示するメニュー画面を作ろう。PCLプロジェクトに[Forms Xaml Page]を1つ追加し、ファイル名を「MasterPage.xaml」とする。「MasterPage.xaml」ファイルは次のコードのように編集する。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="HamburgerMenu.MasterPage"
             Title="MENU"
             >
  <ContentPage.Padding>
    <OnPlatform x:TypeArguments="Thickness" iOS="20"
                Android="0" WinPhone="20,0,20,0" />
  </ContentPage.Padding>
  <!--<Label Text="{Binding MainText}" VerticalOptions="Center"
         HorizontalOptions="Center" />-->
  <TableView Intent="Menu" RowHeight="60">
    <TableView.Root>
      <TableSection Title="メニュー" >
        <TextCell Text="Page 1" TextColor="Accent" Tapped="Menu1_Tapped" />
        <TextCell Text="Page 2" TextColor="Accent" Tapped="Menu2_Tapped" />
        <TextCell Text="Page 3" TextColor="Accent" Tapped="Menu3_Tapped" />
      </TableSection>
    </TableView.Root>
  </TableView>
</ContentPage>

「MasterPage.xaml」ファイル(XAML)
太字の部分を追加/変更した。
これが、左から出てくるメニューの内容になる。
コードビハインドにイベントハンドラーをまだ実装していないので、このままではビルドできない。
MasterDetailコントロールの「Master」画面として使うページには、<ContentPage>タグにTitle属性の指定が必須だ。また、ここでは省略したが、Icon属性も追加してアイコン画像を指定した方がよい(Windows 8.1などで使用される)。

 上のコードには、コードビハインドにイベントハンドラーが必要だが、それは後ほど解説する。

 最後の画面を作ろう。MasterDetailPage画面だ。これは、プロジェクト作成時に自動生成された「MainPage.xaml」ファイルを、次のコードのように編集する。

<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:local="clr-namespace:HamburgerMenu"
                 x:Class="HamburgerMenu.MainPage"
                 MasterBehavior="Popover"
                  >
  <!--<Label Text="Welcome to Xamarin Forms!" VerticalOptions="Center"
           HorizontalOptions="Center" />-->
  <MasterDetailPage.Master>
    <local:MasterPage />
  </MasterDetailPage.Master>
  <MasterDetailPage.Detail>
    <NavigationPage>
      <x:Arguments>
        <local:DetailPage1 />
      </x:Arguments>
    </NavigationPage>
  </MasterDetailPage.Detail>
</MasterDetailPage>

「MainPage.xaml」ファイル(XAML)
太字の部分を追加/変更した。
ルート要素を「ContentPage」から「MasterDetailPage」に変更した(次に示すように、コードビハインドでも親クラスを変更する)。
MasterDetailPageコントロールには2つの要素を置く。<MasterDetailPage.Master>要素と<MasterDetailPage.Detail>要素である。
<MasterDetailPage.Master>要素には、メニューとなるMasterPage画面を収める。
<MasterDetailPage.Detail>要素には、NavigationPageコントロールを収め、その中に「DetailPage1.xaml」画面を配置した(起動時に表示される画面となる)。
なお、<MasterDetailPage>タグに付けた「MasterBehavior="Popover"」という指定は、メニューを自動的に隠す設定である。この設定がないと、デスクトップで実行したときにメニューが出たままになる。

 また、「MainPage.xaml.cs」ファイルも、次のコードのように親クラスを変更する。

……省略……
public partial class MainPage : MasterDetailPage
{
  public MainPage()
  {
    ……省略……

「MainPage.xaml.cs」ファイル(C#)
継承元クラスをContentPageからMasterDetailPageに変更した。

 これで画面がそろった。

 最後に、MasterPage画面(=メニューの内容)のコードビハインドに、メニューを選んだときのイベントハンドラーを実装する。<MasterDetailPage.Detail>要素に入っているNavigationPageコントロールのNavigationプロパティに対してPushAsyncメソッドを呼び出すと、画面遷移するのだ(詳しくは「.NET TIPS:Xamarin.Forms:画面遷移するには?」を参照)。

 「MasterPage.xaml.cs」ファイルを次のコードのように編集する。

……省略……
public partial class MasterPage : ContentPage
{
  public MasterPage()
  {
    InitializeComponent();
  }

  // Detailページを画面遷移させるメソッド
  void Navigate<P>() where P: Page, new()
  {
    // MainPageオブジェクトを取り出す
    var mainPage = this.Parent as MainPage;
    // MainPageのDetailセクションに入っているページオブジェクトを取り出す
    var detail = mainPage.Detail;
    if (detail.Navigation.NavigationStack.LastOrDefault() is P)
      return; //現在表示中と同じページなら、画面遷移しない

    // 画面遷移する
    detail.Navigation.PushAsync(new P(), true);
    // メニューを閉じる
    mainPage.IsPresented = false;
  }

  // イベントハンドラー
  protected void Menu1_Tapped(object sender, EventArgs e)
    => Navigate<DetailPage1>();
  protected void Menu2_Tapped(object sender, EventArgs e)
    => Navigate<DetailPage2>();
  protected void Menu3_Tapped(object sender, EventArgs e)
    => Navigate<DetailPage3>();
}
……省略……

「MasterPage.xaml.cs」ファイル(C#)
このTappledメソッドの書き方は「.NET TIPS:構文:メソッドやプロパティをラムダ式で簡潔に実装するには?[C# 6.0]」を参照。

 以上で完成である。実行してみると次の画像のようになる([DetailPage3]に遷移した状態)。

実行中の様子(Visual Studio Emulator for Android)
実行中の様子(iOS Simulator for Windows)
実行中の様子(Mobile Emulator) 実行中の様子
ハンバーガーメニューを使って[DetailPage3]に遷移した後の状態。
上はVisual Studio Emulator for Androidでの実行結果。中はiOS Simulator for Windowsでの実行結果。下はMobile Emulator(Windows 10)での実行結果。なお、iOS Simulator for Windowsは本稿執筆時点でプレビューとなっている。使用方法については「XamarinアプリのMacでのビルドとiOS Simulator for Windows」を参照されたい。

 上の3つの画像を見て気が付かれただろうか? 自動的にプラットフォームに応じたUIになっているのだ。Androidでは、前の画面に戻るためのボタンが左上に表示されている。iOSでは、リンクだ。Windows Phoneでは[戻る]ボタンは表示されていないが、NavigationPageクラスを利用したことでハードウェアの[戻る]ボタンに対応している。

 Xamarin.Formsのコントロールを使うと、このようにプラットフォームに応じたUIになるのである。

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

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

メールマガジン登録

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