第2回 Japan Xamarin User Group Conference 東日本編 : ATND
https://atnd.org/events/57246/
で 50分ほど頂いたので、Xamarin.Forms の概要ともうちょっと突っ込んだ話をします。
当日、聴衆の様子を見てから判断しますが、Xamarin.Forms の概要は、概要は Xamarin のホームページにあるし、日本語の情報もちらちらと揃っているので「概要」だけ聞かされても面白くない、って方が多い(私もその一人)と思われるので、
- Xamarin.Forms のざっと概要を 15 分程度
- カスタムコントロールを作る話を残りの時間で
ってことを考えます。カスタムコントロールは、いくつか方法があって、その中で 3 つの方法を紹介します。
- 既存のコントロールを継承して、Xamarin.Forms 内で完結する方法
- ネイティブ環境(iOS/Android)を使うために DependencyService を使う方法
- カスタムレンダラーを使って、ネイティブ環境(iOS/Android)で描画させる方法
これも、それぞれについては Xamarin サイトや日本語の解説ページがあるのですが、ひとまとめに書いているものが無いのと、それぞれのサンプルが実用的すぎて難しい(!)ので、簡単なサンプルで比較します。
それぞれの解説自体は、本家 Xamarin のドキュメント(英語だけど)に載っている。
- Part 3. XAML Markup Extensions
- Accessing Native Features via the DependencyService
- Customizing Controls for Each Platform
- Creating Mobile Apps with Xamarin.Forms, Preview Edition (Developer Reference) Kindel 版
日本語のサンプルもある。
- Xamarin.Forms でユーザーコントロール的な View を作る — ContentView を継承
- Xamarin.Formsからプラットフォーム固有の機能を利用するには?(DependencyService利用)
- Xamarin.Formsでカメラを使う – Android編 — Custom Renderer 方式
- Xamarin.Forms 「付箋紙を張るやつ」を作ってみた(画面構成)— BoxView とカスタムレンダラー
この他に考えられるカスタムコントロールとしては、
- Xamarin.Forms.Labs を使う(ライブラリを買うとパターン)
- リフレクションを使う(DependencyService と同じだが、インターフェースを定義しない)
ぐらいでしょうか。Xamarin.Forms 用のコントロールもいくつかあるので、それを購入するという方法もある。
話の流れ
- Xamarin.iOS, Xamarin.Android で、ネイティブな環境のアプリを C#(.NET)で作れる。
- UIが別(storyboard, axml)だったので、共通で使える Xamarin.Forms が現れる。
- Xamarin.Forms のベースは XAML になる。
- XAML の規格は Microsoft が公開していて、自由に作れる。
- x:Class, x:Name などが決められている。
- Microsoft の WPF/Sliverlight などの XAML と互換ではないが…いくつか互換がある。
- iOS, Android, Windows Phone(Silverlight) の共通のコントロールが用意されている。
- データバインドが使える。MS-XAML に規定されている {Binding …}
- ドット付の名前 Grid.Row などが使える。これも MS-XAML に規定されている。
- PLC あるは Shared プロジェクトとして作り、UI を共有する。
- ベースコンテナで ContentPage などがある。
- Grid、StackLayout のように MS-XAML と互換がある。
- Xa-XAML は、XAML を解釈したのちに、それぞれの環境のコントロールにレンダリングする。
- MS-XAML は、直接オブジェクトに変換される、という違いがある。
- これは WPF, Silverlight, WinStore-XAML, WP-Xaml とそれぞれ違う
- が、表面上は一緒なので、Xamarin.Forms も MS-XAML と同様に扱える。
- 大抵は StackLayout と Grid を使いこなすと良い。
- それぞれのプラットフォームの最大公約数なので、プラットフォーム特有の機能がない。
- タップイベントやドラッグがないのが辛いところ。
- 独自のコントロールや、機種ごとの機能を使うことができる。
- 独自コントロールは、MS-XAML のユーザコントロールと似たように、既存のコントロールを組み合わせられる
- ContentPage を継承した例が多いが、View を継承しても作ることができる。
- xmlns:local=”clr-namespace=…” を使って、独自アセンブリをロードする
- <local:CustomButton…> のように書く。
- が、StackLayout の最後に計算されるという Bug ? がある。
- DependencyService を使って、プラットフォーム毎の機能を使う。
- 要するに intarface を利用した委譲パターン(Listenパターン?)
- インターフェースを PCL 側に定義する
- 内部動作を iOS/Android 側で実装する。
- [assembly: Dependency … ] を定義する
- DependencyService.Get<…> で呼び出す。
- 実装がないときは null になる(コードを変えなくて良い利点がある)。
- このテクニックは、共通処理を PCL で書き、それぞれの動作をプラットフォーム毎に書くパターンと同じなので、UI だけでなく普通の処理にも使える(機種番号を拾うとか、独自のフォルダアクセスとか)
- カスタムレンダラを使う
- 独自コントロールの内部動作だけ、プラットフォームに依存させる。
- PCL に既存コントロールを継承したクラスを作る。
- 実行時のレンダリングを、iOS/Android で OnElementChanged として書く。
- たとえば Entry コントロールの場合は、レンダリング用の EntryRenderer が定義されている。
- ASP.NET のユーザコントロールの作り方に似ている。
- ネイティブコントロール(iOS/Android)を自由に扱える。
- 独自コントロールは、MS-XAML のユーザコントロールと似たように、既存のコントロールを組み合わせられる
- 使い分ける
- 共通画面や共通部品は、Xamarin.Forms の基本コントロールをまとめて扱う。
- 独自のプロパティを作って、データバインディングすると再利用性が高まる。
- XAML, コードのコピペではなく、ライブラリとして提供できる。
- DependencyService は、ピンポイントで機種依存の機能を使う。
- 共通のインターフェースを必要とするが、自分で定義できる。
- PLC 内では Device で分岐させることも可能
- ただし、iOS, Android, WP Silverlight 限定になるが… Device クラスを独自に作ることも可能。
- UI がある場合は、カスタムレンダラを使う。
- 応用範囲が広い
- 必ず、Xamarin.Forms のコントロールを継承する必要あり? Renderer なので。
- OnElementChanged 内で、マウスイベントを取ることも可能?
- グラフィック表示
- マウスイベントの取得
- アニメーション処理
- 機種ごとに、Xamarin.iOS/Android が使える。
- 共通画面や共通部品は、Xamarin.Forms の基本コントロールをまとめて扱う。
これに図を加える。