Xamarin.Forms の話ともうちょっと突っ込んだ話…のメモ書き

第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 のドキュメント(英語だけど)に載っている。

日本語のサンプルもある。

この他に考えられるカスタムコントロールとしては、

  • 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)を自由に扱える。
  • 使い分ける
    • 共通画面や共通部品は、Xamarin.Forms の基本コントロールをまとめて扱う。
      • 独自のプロパティを作って、データバインディングすると再利用性が高まる。
      • XAML, コードのコピペではなく、ライブラリとして提供できる。
    • DependencyService は、ピンポイントで機種依存の機能を使う。
      • 共通のインターフェースを必要とするが、自分で定義できる。
      • PLC 内では Device で分岐させることも可能
        • ただし、iOS, Android, WP Silverlight 限定になるが… Device クラスを独自に作ることも可能。
    • UI がある場合は、カスタムレンダラを使う。
      • 応用範囲が広い
      • 必ず、Xamarin.Forms のコントロールを継承する必要あり? Renderer なので。
      • OnElementChanged 内で、マウスイベントを取ることも可能?
        • グラフィック表示
        • マウスイベントの取得
        • アニメーション処理
      • 機種ごとに、Xamarin.iOS/Android が使える。

これに図を加える。

カテゴリー: Xamarin パーマリンク