Xamarin.Forms 2.2から Layout.Children
や ContentView.Content
に各プラットフォームのネイティブコントロールを埋め込めるようになり、Evolve 2016のキーノートでも紹介されました。
このフィーチャーを使うとCustomRendererよりもカジュアルにネイティブコントロールを利用できます。
キーノートのブログ
Live from Evolve: Faster and Easier Mobile App Development with Xamarin.Forms | Xamarin Blog
ドキュメント
条件
ネイティブコントロールの埋め込みを行うにはSharedプロジェクト内のコードで、プラットフォーム毎に#ifディレクティブで記述します。PCLプロジェクトでは使用できません。
サンプルコード
次のようなコードをSharedプロジェクトに追加すると、ネイティブコントロールを埋め込む事ができます。
using System; using Xamarin.Forms; #if __IOS__ using Xamarin.Forms.Platform.iOS; using UIKit; #elif __ANDROID__ using Xamarin.Forms.Platform.Android; using Android.Widget; #endif namespace XFApp25 { public class MyPage : ContentPage { public MyPage () { var text = "Embedded Platform-Specific Control in Xamarin.Forms"; var stackLayout = new StackLayout { VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center, }; #if __IOS__ var uiLabel = new UILabel { MinimumFontSize = 14f, Lines = 0, LineBreakMode = UILineBreakMode.WordWrap, Text = text + "(iOS)", }; // StackLayoutにUILabelが追加できる! stackLayout.Children.Add (uiLabel); // これもOK //Content = uiLabel.ToView (); #elif __ANDROID__ var textView = new TextView(Forms.Context) { Text = text + "(Android)", TextSize = 14, }; stackLayout.Children.Add (textView); // これもOK //Content = textView.ToView (); #endif Content = stackLayout; } } }
仕組み
LayoutExtensionsクラスに定義された2つの拡張メソッドが使用します。
- ToView - ネイティブコントロールをラップしてXamarin.FormsのViewに変換する拡張メソッド
- Add - IList<View>、つまりLayout.Childrenに対する拡張メソッド(内部でToViewを呼ぶ)
これらの拡張メソッドを使うためには各名前空間の参照が必要です。
- iOS – Xamarin.Forms.Platform.iOS
- Android – Xamarin.Forms.Platform.Android
- Windows Runtime – Xamarin.Forms.Platform.WinRT
- Universal Windows Platform (UWP) – Xamarin.Forms.Platform.UWP
ToView拡張メソッドがネイティブコントロールを NaitiveViewWrapper
に変換し、 NaitiveViewWrapperRenderer
が汎用的なViewRendererとして働く、という具合ですね。
込み入ったコントロールのために、サイズ決定時に呼ばれるデリゲートなどを渡すことも出来ます。