LoginSignup
3
2

More than 5 years have passed since last update.

Xamarin.FormsでNative View(Binding Objective-C Libraries使用)の導入メモ

Last updated at Posted at 2017-03-24

2017/04/28 AndroidのNativeViewの利用について説明追加

Xamarin.Forms2.3.3から追加されたNative Viewsを使用したメモ
この記事はNative Viewsの導入方法を説明する内容ではなく、
導入に際してはまった問題や、ここはまるなーと思ったポイントのメモとなる

導入については下記公式の記事を見るかぴーさんのブログを見るといい

バインディングライブラリについては下記を参照

前提条件

  • 母艦はWin10でVisualStudio2015使用(MacBookProも別途利用)
  • Xamarin.FormsアプリPCLプロジェクトでiOSとAndroidに対応
  • Xamarin.Formsのバージョンは2.3.3

目的

Xamarin.Forms PCLプロジェクトでiOSのNative Views(外部SDK提供物)を利用する

導入理由

サードパーティのObjective-Cライブラリを使用する必要があり、
ライブラリで提供されるネイティブViewの利用が必須だった為

はまりポイント

VS2015ではiOSバインディングプロジェクトのインテリセンスが効かない

NativeViewsは関係なくバインディングプロジェクトの問題
インテリセンスが効かないのはXamarinのバグ仕様である
対処法はプロジェクト参照をやめて作成されたdllをアセンブリ参照すれば良い
詳細な情報が知りたい場合は下記のURLを参照
https://bugzilla.xamarin.com/show_bug.cgi?id=18815
https://forums.xamarin.com/discussion/16164/intellisense-on-projects-referencing-a-binding-project-doesnt-work

PCLの場合NativeViewsはXamlのみ対応(コードビハインドは非対応)

コードビハインドで作成していた場合、Xamlで書き直す必要がある

XamlCompilationOptions.Compileでは動作しない

ビルドエラーも実行時エラーも発生しないで、単純に動かないだけなのでわかりにくい
テンプレートからXamlを作成している場合、初期でCompile設定になっている為、気が付かない恐れがある

アセンブリ名を間違えた場合の例外がわかりにくい

例えばアセンブリ名が「MyApp.iOS」が正解なところ間違えて「MyAppiOS」と入力して実行した場合に発生する例外メッセージは
「MyView not found in xmlns clr-namespace:MyApp.iOS;assembly=MyAppiOS;targetPlatform=iOS
」となり、
アセンブリ名を間違えているのに、あたかもMyAppiOSというアセンブリは存在するが使いたいViewが見つからない印象を与える

xaml
xmlns:ios="clr-namespace:MyApp.iOS;assembly=MyAppiOS;targetPlatform=iOS"
<ios:MyView />

プロパティに対するBindingに対応しているが、Getterを作っておかないと実行時例外が発生する

動作する例

Xaml
<ios:MyView Text="test" />
C#
public class MyView : UIView
{
    public string Text { set; }
}

上記のXamlコードを下記のようにBindingに書き直すと動かなくなる
実行時例外が発生するがメッセージは上記アセンブリ名を間違えたときと同じメッセージしか得られない

Xaml
<ios:MyView Text="{Binding TestText}" />

動作させるにはC#側にgetterを作成する

C#
public class MyView : UIView
{
    public string Text { get; set; }
}

Bindingを利用しないで直接代入する場合はGetterがなくても動作するのが厄介

使いたいNativeViewsの初期化に指定されたイニシャライザの利用が必要だった

ライブラリで提供されているViewが既定のコンストラクタを使って初期化すると動かない仕様であった為、単純にXaml側に記載しても動かなかった
具体例を挙げて説明すると
ライブラリで提供されているNativeViewのクラス名が「SdkButton」だった場合

Xaml
<ios:SdkButton />

と単純に書いても動作しないViewであった
このSdkButtonクラスには静的なメソッドでSdkButtonインスタンスを返すメソッド「ButtonWithType(UIButtonType type)」が用意されており
このメソッドを通してインスタンス化しないと使えないつくりとなっていた

なので下記のようなつくりにする必要があった

Xaml
<ios:MySdkButton />
C#
public class MySdkButton : UIView
{
    private SdkButton _SdkButton;

    public MySdkButton()
    {
        _SdkButton = MySdkButton.ButtonWithType(UIButtonType.RoundedRect);
        AddSubview(_SdkButton);
    }
}

SdkButtonを直接Xamlで使うのではなく、MySdkButtonというクラスを通して
SdkButtonを表示するようにする

MySdkButtonは内部にSdkButtonをもっておりここで初期化を行う

Viewの初期化に引数が必要(Android)

Androidの場合、Contextを引数に取るものが多い
XamlからContextを渡すには下記のようにする

xaml
xmlns:formsAndroid="clr-namespace:Xamarin.Forms;assembly=Xamarin.Forms.Platform.Android;targetPlatform=Android"

<droid:MySdkButton x:Arguments="{x:Static formsAndroid:Forms.Context}" />
C#
public class MySdkButton : SdkButton
{
    public (Context context) : base(context) { }
}
3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2