読者です 読者をやめる 読者になる 読者になる

Xamarin 日本語情報

Xamarin(ザマリン) の代理店だったエクセルソフト田淵のブログです。主に Xamarin に関するエントリーをアップしていきます。(なるべく正しい有益な情報を掲載していきたいと考えていますが、このブログのエントリーは所属組織の公式見解ではありませんのでご注意ください)

Xamarin.Forms で MasterDetailPage を使うには

こんにちは。エクセルソフトの田淵です。

2015/7/23 現在の Xamarin for Visual Studio 3.11.666 と Xamarin.Forms 1.4.3.6376 での情報です。

前回 Xamarin.Forms の NavigationPage に ToolbarItem を追加するには - Xamarin 日本語情報 で ToolbarItem の使い方をご紹介しました。シンプルで使いやすいのですが、複数のメニューを用意する場合はやはり MasterDetail が必要です。

個人的には Xamarin.Forms の Android プロジェクトには v7 AppCompat が含まれているので Material Design v7 AppCompat を使用するには (Xamarin.Android) - Xamarin 日本語情報 で紹介した Toobar にマッピングしてくれてたら嬉しいのですが、iOS に Toolbar っぽいの無いから Custom Renderer するしか無いかなぁという感じですね…

この前 Xamarin MVP になられた Adam さんの Xamarin.Forms Recipe が最強に分かりやすいので、こちらをそのままご紹介します。

Xamarin.Forms MasterDetail Page Navigation Recipe

こんな感じです。

f:id:ytabuchi:20150723183314g:plain:w450

WinPhone だと ToolbarItem とあまり変わらないですね。
f:id:ytabuchi:20150724164427g:plain:w200

MasterDetailPage とは?

上記のような画面左からスワイプまたは左上の文字/画像をタップするとスライドして出て来るページです。

使い方の基本

MasterDetailPage を継承したページを使います。

Master が左側のメニューページで、Detail が右側の普段見るページです。

Master には今回はベーシックな ListView を使用していますが、Xamarin.Forms in Anger - Jobbberr - Syntax is my UI のように自由に作成することができます。設定用ページに飛ばすも良し、このページで設定させるも良し。です。

タップ出来ないと行けないので今回の ListView みたいにやるのが楽かなとは思います。

コード

全部纏めて書いてしまいましたが、Adam さんはちゃんと分割しています。ソースは Adam さんのブログ から落として頂ければと思います。

Xaml で書くのは私の力量だと今はちょっと難しいです。すみません。どなたか書いてくれないかなー (チラッチラッ

/// <summary>
/// MasterDetailPage の定義です。Master(左側) と Detail(各子ページ) を指定します。
/// </summary>
public class RootPage : MasterDetailPage
{
    public RootPage()
    {
        var menuPage = new MenuPage();
        // Menu ページの ListView Menu を選択した時に NavigateTo メソッドに SelectedItem を渡します。
        menuPage.Menu.ItemSelected += (sender, e) => NavigateTo(e.SelectedItem as MenuItem);

        Master = menuPage;

        // Detail は NavigationPage で呼び出した方が良いです。(左からのスワイプで Master を出せるが操作しづらい)
        // バーの色を変えています。
        var detail = new NavigationPage(new ContractsPage());
        detail.BarBackgroundColor = Color.FromHex("3498DB");
        detail.BarTextColor = Color.White;
        Detail = detail;

    }

    /// <summary>
    /// ページ遷移のメソッドです。
    /// </summary>
    /// <param name="menu">MenuItem</param>
    void NavigateTo(MenuItem menu) {
        // menuPage の List<MenuItem> の選択値を MenuItem で受け取っているので
        // 予め定義されたページに移動できるってことは分かるんですが、凄いですね。
        Page displayPage = (Page)Activator.CreateInstance(menu.TargetType);

        // 同じく各ページに移動する時にもバーの色を再設定 (このやり方では必須)
        var detail = new NavigationPage(displayPage);
        detail.BarBackgroundColor = Color.FromHex("3498DB");
        detail.BarTextColor = Color.White;
        Detail = detail;

        IsPresented = false;
    }
}

/// <summary>
/// 左側のメニューページクラスです。
/// </summary>
public class MenuPage : ContentPage
{
    public ListView Menu { get; set; }

    public MenuPage()
    {
        Icon = "settings.png"; // Icon を設定すると左側が文字でなくアイコンで置き換わります。
        Title = "Menu"; // Icon を指定しても Title プロパティは必須項目です。
        BackgroundColor = Color.FromHex("dce8ef");

        // ListView 設定
        Menu = new MenuListView();

        var menuLabel = new ContentView
        {
            Padding = new Thickness(10, 36, 0, 5),
            Content = new Label
            {
                TextColor = Color.FromHex("333"),
                Text = "MENU",
                FontSize = 18,
            }
        };

        // タイトルの menuLabel と ListView を並べています。
        var layout = new StackLayout
        { 
            Spacing = 0, 
            VerticalOptions = LayoutOptions.FillAndExpand
        };
        layout.Children.Add(menuLabel);
        layout.Children.Add(Menu);

        Content = layout;
    }
}

/// <summary>
/// ListView を継承したクラスです。ItemsSource で List<MenuItem>、ItemTemplate で ImageCell を使用しています。
/// </summary>
public class MenuListView : ListView
{
    public MenuListView()
    {
        List<MenuItem> data = new MenuListData(); // インスタンス化して、
        ItemsSource = data; // ItemsSource として指定します。
        VerticalOptions = LayoutOptions.FillAndExpand;
        BackgroundColor = Color.Transparent;

        // ItemTemplate で使用しているのが ImageCell なので Android では Text が水色になってしまいます。
        // 嫌な場合は ImageCell ではなく ViewCell で ItemTemplate を作りましょう。
        var cell = new DataTemplate(typeof(ImageCell));
        cell.SetBinding(TextCell.TextProperty, "Title");
        cell.SetBinding(ImageCell.ImageSourceProperty, "IconSource");

        ItemTemplate = cell;
    }
}

/// <summary>
/// ListView のデータ用のクラスです。TargetType に遷移先ページを指定します。
/// </summary>
public class MenuItem
{
    public string Title { get; set; }

    public string IconSource { get; set; }
    // この Type で移動先のページクラスを指定しています。
    public Type TargetType { get; set; }
}

/// <summary>
/// ListView のデータクラスです。
/// </summary>
public class MenuListData : List<MenuItem>
{
    public MenuListData()
    {
        this.Add(new MenuItem()
            { 
                Title = "Contracts", 
                IconSource = "contacts.png", 
                TargetType = typeof(ContractsPage)
            });

        this.Add(new MenuItem()
            { 
                Title = "Leads", 
                IconSource = "leads.png", 
                TargetType = typeof(LeadsPage)
            });

        this.Add(new MenuItem()
            { 
                Title = "Accounts", 
                IconSource = "accounts.png", 
                TargetType = typeof(AccountsPage)
            });

        this.Add(new MenuItem()
            {
                Title = "Opportunities",
                IconSource = "opportunities.png",
                TargetType = typeof(OpportunitiesPage)
            });
    }
}

Xamarin 気になった方は

是非 ダウンロード(直接) / ダウンロード(弊社経由) して触ってみてください。 学習用リソースJXUG リンクページ に参考資料を纏めてますので併せてどうぞ。

Xamarin の情報が欲しい方はこのブログも購読いただいたりすると嬉しいです。

以上です。