Xamarin.Forms の Native Embedding を試してみた(失敗談)

昨日行われた「JXUGC #18 Xamarin.Forms & Prism & Azure Mobile Apps を使いこなそう」で @AyaseSHさん が発表された Native Embedding を試してみました.

eventdots.jp

公式ドキュメントはこちら.

developer.xamarin.com

ぴーさん の素晴らしい解説記事はこちら.

これらを参考にしながら Xamarin.Forms PCL プロジェクトで Android.Support.Design.Widget.FloatingActionButton を XAML に配置してみました.

ちなみに、今回のは失敗例で、実用できる状態まで行ってませんw

なお、間違った解釈が多分に含まれている可能性があります.そのときはご指摘いただけますと嬉しいです.

実装環境

  • Windows 10 Home
  • Visual Studio Enterprise 2015 14.0.25123.00 Update 2
  • Xamarin 4.2.0.703 (3b7df6f)
  • Xamarin.Android 7.0.1.3 (96c7ba6)

Xamarin.Forms 23.3.3.152-pre2 のインストール

XAML にネイティブコントロールの埋め込みができるようになったのは Xamarin.Forms 2.3.3 -pre2 からなのでこれをインストールします.

Prism のテンプレートから Xamarin.Forms を更新すれば普通にいけるかなぁと思ったのですが、更新後 Visual Studio を再起動すると

“パッケージをパス ‘Xamarin.Forms.2.3.3.152-pre2\Xamarin.Forms.2.3.3.152-pre2.nupkg” から読み込めません。
ファイルのデータが壊れています。”

と表示されビルドできなくなったので、おとなしく Xamarin.Forms のアンインストール → 再度インストール という手順を取りました.

Xamarin やってると、ちょっとやそっとのエラーじゃ驚かなくなってきましたねw

XAML

ContentPage に FloatingActionButton を配置した状態です.

FloatingActionButton を配置した XAML です.

要素を1つずつ見ていきます.

Android.Widget の assembly が “Mono.Android” だったのに対し、Android.Support.Design.Widget の assembly は Xamarin.Android.Support.Design になります.

ネイティブコントロールの引数用の xmlns:formsandroid は同様です.

FloatingActionButton には引数なしコンストラクタが存在しないため、引数を指定します.

おそらく、Android の View 全般にこのことは言えて、引数に Context が必要です.

FloatingActionButton にも Width/MinimumWidth といったプロパティはありますがことごとく読み取り専用プロパティです.

ネイティブコントロールをラップするViewのパラメータに値やBindingをセットすることも可能です。(“View.BackgroundColor=〜〜”の部分) ラッパーである NativeViewWrapper クラスは View のサブクラスなので、指定できるプロパティはViewと同じと考えれば良いでしょう。

ぴーさんが述べられているように、View のプロパティを使って代用します.

UseCompatPadding=”true” を指定しないと影が見切れてしまいます.

なので true にするのですが、今度は影の分のマージンで横長になってしまうので、Height を大きめにとっています.

ここらへんは Android のお作法だった気がするのですが、正確に覚えてないです.ごめんなさい.

Xamarin.Android.Design の最新版(24.2.1) では “Size” というプロパティが実装されているので、こんな感じにスマートに書けるようになると思われます.

読み取り専用プロパティの制限が厳しい

さきほどの描画結果で、FAB に画像が付いていなかったことにお気づきでしょうか.

たぶん、XAML 埋め込みで FAB に画像を付けることはできません(泣)

どういうことかというと、FAB の画像は Drawable というプロパティで定義されていますが、こいつは読み取り専用プロパティなんです.

public virtual Drawable Drawable { get; }

通常は SetImageResource(int resId) を使って画像をセットします.

でも!XAML 埋め込みはコードビハインド使えない!!

オワタ\(^o^)/

Android の画像系のビューは全体的にこのような状態に陥ると思います.
(iOS は知らない)

で、Native Embeddingって使えるの?って話ですが、

  • 読み取り専用プロパティの制限が厳しい
  • XAML でインテリセンスが効かない
  • 実行時解釈でデバッグしづらい

という理由で、ぶっちゃけ CustomRenderer で良くね? という結論に落ち着きつつあります.

なにかよっぽど使いやすいネイティブビューでもあれば使いどころになるかもしれません.
(聞きかじった程度ですが、RichTextBox とかは使いやすいのかも?)

私自身、よくわからない部分が多いので、ご意見・ご感想ありましたらぜひお願い致します.

以上です.