Xamarin.Forms のサンプルに
https://github.com/moonmile/XFormsGallery
ところどころ未完成なところがあるのですが、ひとまず1日で出来上がったところまで。
共通プロジェクトは PCL を使っています。XAML を素直に共通化するだけであれば PCL で良いでしょう。WinStore/WinPhone のユニバーサルプロジェクトのようにコードビハイドに手を加える場合には、共有プロジェクトを使うと良いかと。
■注意
現時点の Xamarin.Formsのバージョンは「1.1.1.6206」になっているのですが、Visual Stuido 2013 に含まれているテンプレートでは、「1.0.6186」になっています。ほとんど変わらないですが TableView の概観がちょっと違うので、Xamarin の Sample のように、最新のバージョンに合わせています。プロジェクトごとに NuGet で最新にしてください。
以下、ざっと XAML にするときに手順を書き下しておきます。
■App.cs を書き換える
プロジェクトテンプレートで作ると、PCL プロジェクトの App.cs にページを作るコードがあります。ここをごっそり削って、Page クラスのインスタンスを返します。ただし、サンプルの場合には特殊でナビゲーションを使っています。この場合は特別に NavigationPage のインスタンスを作成します。
public class App { public static Page GetMainPage() { return new NavigationPage(new HomePage()); } }
■簡単な LabelDemoPage を作る
ラベルだけが表示されるページはこんな感じです。
<?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="XFormsGallery.LabelDemoPage"> <ContentPage.Padding> <OnPlatform x:TypeArguments="Thickness"> <OnPlatform.iOS>10,20,10,5</OnPlatform.iOS> <OnPlatform.Android>10,0,10,5</OnPlatform.Android> <OnPlatform.WinPhone>10,0,10,5</OnPlatform.WinPhone> </OnPlatform> </ContentPage.Padding> <StackLayout> <Label Text="Label" Font="50" HorizontalOptions="Center"></Label> <Label Font="Large" VerticalOptions="CenterAndExpand"> <Label.Text>Xamarin.Forms is a cross-platform natively backed UI toolkit abstraction that allows developers to easily create user interfaces that can be shared across Android, iOS, and Windows Phone.</Label.Text> </Label> </StackLayout> </ContentPage>
OnPlatform のところは、OSによってコードを切り替えらるところで、元のサンプルの Device.OnPlatform にあたります。Top だけ切り替えられるような気もするのですが、うまくいかなかったので Thickness まるごと切り替えます。iOS だけ 20 ドット広げてあるのは、iPhone のステータスバー用です。ただし、ナビゲーターの場合は自動でステータスバーに対応しているらしく、これはあまり意味がありません。全画面表示するページを作るときに使う技ですね。
元ネタの LabelDemoPage を見ると、次のようになるので、解りやすいような解りにくいような。
class LabelDemoPage : ContentPage { public LabelDemoPage() { Label header = new Label { Text = "Label", Font = Font.BoldSystemFontOfSize(50), HorizontalOptions = LayoutOptions.Center }; Label label = new Label { Text = "Xamarin.Forms is a cross-platform natively " + "backed UI toolkit abstraction that allows " + "developers to easily create user interfaces " + "that can be shared across Android, iOS, and " + "Windows Phone.", Font = Font.SystemFontOfSize(NamedSize.Large), VerticalOptions = LayoutOptions.CenterAndExpand }; // Accomodate iPhone status bar. this.Padding = new Thickness(10, Device.OnPlatform(20, 0, 0), 10, 5); // Build the page. this.Content = new StackLayout { Children = { header, label } }; } }
XAML 自体は、Xamarin Studio 上で手書きをします。Visual Studio 上でも書けないことはないのですが、タグのコード補完が効かないので、非常にやりにくいです。本当はデザイナが欲しいところでしょうが、スマートフォンのような小さな画面の場合には自由度が少ないので、ほとんど StackLayout か Grid を使ってしまうのであまり関係ないでしょう。ですが、iPad や Surface のようなタブレットPC のレイアウトをするときにはデザイナは必須ですよね。このあたりは、今後どうするのか不明です。
Windows Phone(SilverLightですが)の XAML に直す時に ConvertPageToUIElement メソッドを呼び出しているので、この逆変換ができれば Visual Studio 上で XAML のデザインができるようになるかもしれません。
■HomePage ページを作る
トップページは、メニュー用のページです。
TableView でリスト表示をしているのですが、この親子関係が解りづらいところです。
<?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="XFormsGallery.HomePage" Title="XAML Forms Gallery"> <TableView Intent="Menu"> <TableView.Root> <TableSection Title="Views for Presentation"> <TextCell Text="Label" x:Name="cellLabel" ></TextCell> <TextCell Text="Image" x:Name="cellImage"></TextCell> <TextCell Text="BoxView" x:Name="cellBoxView"></TextCell> <TextCell Text="WebView" x:Name="cellWebView"></TextCell> <TextCell Text="Map" x:Name="cellMap"></TextCell> </TableSection> <TableSection Title="Views that Initiate Commands"> <TextCell Text="Button" x:Name="cellButton" ></TextCell> <TextCell Text="SearchBar" x:Name="cellSearchBar"></TextCell> </TableSection> ...
ただし、元ネタの HomePage.cs を覗いてみると、TableView <- TableView.Root <- TableRoot <- TableSection <- TextCell <- TextCell の関係が解るので、そのまま書き写しています。XAML では TableRoot を省略しても動作するようです(TableView.Rootのほうは省略できないんですよね。ここは Children にして欲しかった)。
this.Title = "Forms Gallery"; this.Content = new TableView { Intent = TableIntent.Menu, Root = new TableRoot { new TableSection("Views for Presentation") { new TextCell { Text = "Label", Command = navigateCommand, CommandParameter = typeof(LabelDemoPage) }, new TextCell { Text = "Image", Command = navigateCommand, CommandParameter = typeof(ImageDemoPage) },
タップなどの操作は非常に制限されています。労力を減らすたか、これから実装するのか解りませんが、TextCell の場合は Command パターンで呼び出しをしています。ただし、主要なボタンコントロールなどには Clicked イベントが用意されているので、そのままコードビハイドで書くことができます。
WPFやWinStoreで XAML を手書きしたことがある人ならば、デザイナがなくても大体想像して書けるかなという感じですね。Xamarin.Forms の DTD は無いようなので、親子関係はマニュアル http://iosapi.xamarin.com/?link=N%3aXamarin.Forms を見る必要があるのですが、まあ元ネタを見比べていけば、これも想像で書ける範囲かと思います。