Xamarin.Forms ページ(Formsを使用したアプリ作成の第1歩)

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

今回は、「Xamarinによる3種類のアプローチ」で紹介した3つのアプローチの最後であるXamarin.Formsについてです。

Xamarin.Formsは、iOS や Android のライブラリとは全くの別物であり、完全に独自のライブラリとなっています。従って、既存の知識を頼りにすることはできず、一から学ぶ必要があります。 しかし、このライブラリを使用すると、iOS、Android、Windows Phone (ストアアプリにも対応中) 用のネイティブアプリが一気に作成できてしまいます。

2 ページクラス

Xamarin.Formsで画面を構成するには、最初にページクラスを理解する必要があります。


Xamarin Developers Guide 「Xamarin.Forms Pages」

ページクラスは、画面のすべて(若しくは殆どすべて)を占有し、単一の子要素を含むビジュアル要素です。AndroidでのActivity、iOSでのView Controller、WindowsPhoneでのPageと同じようなイメージです。

Xamarin.FormsのPageクラスは、次の5つがあります。

  • ContentPage
  • MasterDetailPage
  • NavigationPage
  • TabbedPage
  • CarouselPage

以下、各ページクラスを、可能な限りシンプルなサンプルで紹介したいと思います。

(1) ContentPage

iOS Android WindowsPhone
Page001 Page002 Page003

単一ページとなり、Contentプロパティに任意のViewコントロールを子要素として配置できます。 複数のコントロールを配置する際には、StackLayoutやScrollViewが、よく利用されます。

public class App : Application {
    public App() {
        // MyContentPagePageを継承したクラスを生成してMainPageとする
        MainPage = new MyContentPage();
    }
}

class MyContentPage : ContentPage {
    public MyContentPage() {
        //iPhoneにおいて、ステータスバーとの重なりを防ぐためパディングを調整する
        Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0);
        //ラベルを1つ生成
        var label1 = new Label {
            FontSize = 40,
            Text = "Developers.IO"
        };
        // 生成したラベルをこのビューの子要素とする
        Content = label1;
    }
}

(2) MasterDetailPage

iOS Android WindowsPhone
Page004 Page005 Page006

概要レベルで要素を一覧するマスターページと、各要素の詳細ページを管理するページです。通常、マスターページがメニュー的な役割を担うことになると思います。

public class App : Application {
    public App() {
        // MasterDetailPageを継承したクラスを生成してMainPageとする
        MainPage = new MyMasterDetailPage();
    }
}

class MyMasterDetailPage : MasterDetailPage {
    public MyMasterDetailPage() {
        var ar = new[] { "Ietm1", "Item2", "Item3" };

        ListView listView = new ListView {
            ItemsSource = ar,
            BackgroundColor = Color.Transparent
        };

        // マスターページ
        this.Master = new ContentPage {
            BackgroundColor = Color.FromRgba(0.86,0.91,0.94,0.5),
            //iPhoneにおいて、ステータスバーとの重なりを防ぐためパディングを調整する
            Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0),
            Title = "Master", // 必須
            Icon = "menu.png",
            Content = listView
        };
        
        // リストが選択された際のイベント処理
        listView.ItemSelected += (s, a) => {
            //プロパティDetailに新しいページをセットする
            Detail = new NavigationPage(new DetailPage(a.SelectedItem.ToString())) {
                //  タイトルバーの背景色や文字色は、NavigationPageのプロパティをセットする
                BarBackgroundColor = Color.FromRgba(0.2, 0.6, 0.86, 1),
                BarTextColor = Color.White
            };
            IsPresented = false;//  Detailページを表示する
        };
        
        listView.SelectedItem = ar[0];// 必須 最初のページをセットする

    }
}

//詳細ページ
class DetailPage : ContentPage {
    public DetailPage(string title) {
        Title = title;
         Content = new Label {
            //テキストを中央に表示する
            Text = title,
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center
        };
    }
}

コメントで「必須」となっている箇所は、省略すると例外で落ちます。 また、今回、メニュー表示のために「戻る」機能を利用したくて、DetailにセットするページをNavigationPageにしましたが、これは必須ではありません。(ContentPage等でも問題ありません)

(3) NavigationPage

iOS Android WindowsPhone
Page007 Page008 Page009

iOSのUINavigationControllerと同じイメージです。 遷移元に戻るには、Backボタンを使いますが、WindowsPhoneは、ハードウエアのBackしかありません。

public class App : Application {
    public App() {
        // NavigationPageを使用して最初のページを表示する
        MainPage = new NavigationPage(new MainPage()) {
            //  タイトルバーの背景色や文字色は、NavigationPageのプロパティをセットする
            BarBackgroundColor = Color.FromRgba(0.2, 0.6, 0.86, 1),
            BarTextColor = Color.White
        };
    }
}

//メインのページ
class MainPage : ContentPage {
    public MainPage() {
        Title = "MainPage"; //ページのタイトル

        //ボタンを生成
        var button1 = new Button { Text = "NextPageへ移動" };
        //ボタンクリック時の処理
        button1.Clicked += async (s, a) => {
            //ページを遷移する
            await Navigation.PushAsync(new NextPage());
        };

        Content = button1;
    }
}

//遷移後のページ
class NextPage : ContentPage {
    public NextPage() {
        Title = "NextPage"; //ページのタイトル
    }
}

(4) TabbedPage

iOS Android WindowsPhone
Page010 Page011 Page012

タブで複数のページを切り替えるページです。ネイティブコントロールで描画されることから、タブは、iOSでは下に、Androidでは上に配置されます。 正直な感想ですが、WindowsPhoneはタブじゃない・・・

public class App : Application {
    public App() {
        // TabbedPageをMainPageとしてセットする
        MainPage = new TabbedPage() {
            Children = {
                new MyPage("Tab1"),
                new MyPage("Tab2"),
                new MyPage("Tab3")
            }
        };
    }
}

class MyPage : ContentPage {
    public MyPage(string title) {
        //タブに表示される文字列
        Title = title;
        //ラベルを生成
        var label1 = new Label {
            FontSize = 40,
            //ビューの中央に配置
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center,
            Text = title
        };
        Content = label1;//ラベルのみを配置する
    }
}

(5) CarouselPage

iOS Android WindowsPhone
Page013 Page014 Page015

スワイプによって複数のページをスライドすることができるページです。 WindowPhoneは、ここでも、ループしています。

public class App : Application {
    public App() {
        // CarouselPageをMainPageとしてセットする
        MainPage = new CarouselPage() {
            Children = {
                new MyPage(Color.Green),
                new MyPage(Color.Red),
                new MyPage(Color.Aqua)
            }
        };
    }
}

class MyPage : ContentPage {
    public MyPage(Color color) {
        //ページの区切りが分かりやすいように背景色を設定する
        BackgroundColor = color;
        //ラベルを生成
        var label1 = new Label {
            FontSize=40,
            //ビューの中央に配置
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center,
            Text = string.Format("RGB({0:0},{1:0},{2:0})", color.R, color.G, color.B)
        };
        Content = label1;//ラベルのみを配置する
    }
}

3 まとめ

今回は、Xamarin.Formsを使用する場合に、最初に決めなければならない画面構成であるページクラスについて紹介しました。 個人的な見解ですが、さすがに3つのプラットフォームを跨ぐとなると、ちょっと無理があるものも有るなと思います。

githubサンプルコード(https://github.com/furuya02/Xamarin.Forms.PageSample)

本記事は、2015年10月20日現在で最新の Xamarin.Forms 1.5.1.6468 を使用して作成されています。

4 参考リンク


Xamarin Developers Guide 「Xamarin.Forms Pages」
Xamarin Forms MasterDetail Page Navigation Recipe
Xamarin.Forms で MasterDetailPage を使うには
Xamarin記事一覧(SAPPOROWORKSの覚書)