第1回 Xamarin User Group は無事終了。プレゼン資料については後ほど解説を入れるとして、なにかと気になったので、ちょっと手を付けてみました。
Xamarin.Forms を使うとき、Phone の場合は画面が狭いので手打ちで XAML を書いてもなんとかなるのですが、タブレットのように広い画面になった時や、Xcode の autolayout みたいな感じでレイアウトしようとすると手打ち XAML だけだと結構大変です。実行しないとうまくいかないし、懇親会でもレイアウトに苦労している場面もあったりして、
- エミュレータで実行してみないと、タグの typo が分からない。
- エミュレータで実行してみないと、レイアウト崩れがわからない。
のは、いかんともしがたいところ。Xamarin.Forms 用のデザイナが出ればいいんですが、暫くは出る様子もないので、なんとかならんかなと。そこに、「プレビューでもあれば便利なのに」とのツイートを見つけました。
なるほど、デザイン自体は大変そうだけど、プレビューだけならなんとかなりそうです。
- Xamarin.Froms の XAML を手打ちする。
- 更新されたファイルを読み取って、デザイナに描画する。
程度の繰り返しができればよいわけで、そのサイクルが早く回れば try & error も進みそう。で、なにか方法はないかと思って、ひとつ思いついたのが、
- デザイン用の XAML を手打ちする。
- なんらかの形で iOS/Android のエミュレータにアップ。あるいは、エミュレータからプル。
- なんらかの形で、エミュレータ上で XAML を解析して、レイアウトを作成する。
というパターンです。プレビュー自体をエミュレータ内で動かしてしまえばよいのです。
幸いにして、Xamarin.Forms の場合は、プラットフォーム共通のレイアウトページとして Xamarin.Forms の ContentPage が用意されています。大抵は PCL で作るんですが、この new ContentPage したものを、iOS/Android のプラットフォーム毎に再構成しています。ならば、この new ContentPage のところをすり替えてしまえば、良いわけで実際、XAML のほうではなくて、コードでちまちまと ContentPage を作っているところを、XAML から作り込めるようにすれば良いわけです。
namespace XFormsPreview { public partial class MainPage { public MainPage() { InitializeComponent(); } void OnClickPreview(object sender, EventArgs e) { // var page = new NewPage(); string xml = @"<?xml version='1.0' encoding='utf-8' ?> <Contentpage x:class="XFormsPreview.NewPage"
xmlns:x=http://schemas.microsoft.com/winfx/2009/xaml
xmlns="http://xamarin.com/schemas/2014/forms"> <Stacklayout> <Label Text="New Page"> <Button Text="click me"> </Stacklayout> </Contentpage> "; var page = ContentPageXaml.LoadXaml(xml); this.Navigation.PushAsync(page); } } }
こんな風に文字列で XAML を設定して LoadXml すると ContentPage ができるようにします。ここは F# の Type Provider と似た感じですね。
まだテスト中なので、XAML の文字を埋め込んでいますが、これをエミュレータの動いている PC から XAML ファイルをダウンロードできるようにすれば、XAML の修正とプレビューのサイクルが早くなります。大まかの動きの目途は立ったので、あとはちまちまと Xmarin.Forms のコントロールを移し替えていきます。車輪の再発明ような感じもするし、既にあるような気もするし、本格的なデザイナが出るまでの短い間という訳でもあるけど、ひとまず、一通り動くところまで作ってみる予定。