Xamarinには、Xamarin.Formsの他に「ネイティブUI」という作り方がある(一般には「Xamarin Native」と呼ばれるが、「ネイティブコード」とまぎらわしいので本稿では「ネイティブUI」と呼ぶ)。
ネイティブUIでは、UIの作成はプラットフォームごとの方法による。ただし、コードビハインドに相当する部分はC#で記述する。プラットフォームごとのUIの機能をフルに活用できる上に、C#でコーディングできるのである。
そして、ネイティブUIでも、ロジックのコードを共有できる。PCL(移植可能ライブラリ)や共有プロジェクトとして共通のロジックを記述し、プラットフォームごとのプロジェクトからそのロジックを利用するのである。
ネイティブUIのメリット
実際にネイティブUIのプロジェクトを作って試してみよう(次の画像)。コードの共有方法としてはPCLを使う。
[新しいプロジェクト]ダイアログの左側で[インストール済み]−[テンプレート]の中から[Visual C#]を探し、その下の[Cross-Platform]を選ぶ。ダイアログの中央で[Blank App (Native Portable)]を選び、ダイアログ下側で名前と場所を適宜設定し(日本語を使わずに!)、[OK]ボタンをクリックしてプロジェクトを作成する。なお、以降では、ここでプロジェクトの名前に「NativeUI」と付けたものとする。
プロジェクトが作成できたら、前回の「まずはフルビルド!」で説明したようにUWPアプリのビルド設定も追加してからフルビルドし、デバッグ実行してみよう。
ところで、本稿執筆時点では、以上のようにしてソリューションを作っても、UWPアプリとWindows 8.1用ストアアプリのプロジェクトが生成されない。それら2つのプロジェクトが必要ならば、ソリューションに手動でプロジェクトを追加し、PCLプロジェクトへの参照を追加する。その後、Windows PhoneプロジェクトのXAMLコードとコードビハインド(C#)をUWPプロジェクトに移植したものが、冒頭の画像だ。
ソリューションエクスプローラーでAndroidのプロジェクトを見てみよう(次の画像)。
[NativeUI.Droid]プロジェクトのResources\layoutフォルダーにある「Main.axml」ファイルが、画面定義だ(拡張子は「.xaml」ではなく、「.axml」)。画像の上側の編集ペインで開いている(その下の[Designer]タブでプレビュー画面に切り替わる)。XAMLではないが、Androidの画面定義はこのようなXMLで記述するのだ。
そして、[NativeUI.Droid]プロジェクトの直下にある「MainActivity.cs」ファイルが、アプリ起動時の処理だ(画像の下側の編集ペイン)。23行目の「SetContentView(Resource.Layout.Main);」というコードで、先ほどの「Main.axml」画面を表示しているのが分かるだろうか。コードビハインドに相当する部分は、このようにC#で記述するのである(何行目かはXamarin.Formsのバージョンなどによって異なるかもしれない。以下同様)。
ソリューションエクスプローラーでiOSのプロジェクトを見てみよう(次の画像)。
[NativeUI.iOS]プロジェクトにある「Main.storyboard」ファイルが、画面定義だ。その内容をXMLエディタで開いて、画像の上側の編集ペインに表示している(ソリューションエクスプローラーでダブルクリックして開くと、ストーリーボードをWYSIWYGで編集できる「Xcode Interface Builder Editor」が表示される)。XAMLではないが、iOSの画面定義もこのようなXMLで記述するのだ。XMLコードの下の方(19行目)に<button>タグが見えている。また、上の方(10行目)にはViewControllerを指定しているタグがある。
「Main.storyboard」ファイルで指定されている「ViewController.cs」ファイルが、コードビハインドに相当するコードだ(画像の下側の編集ペイン)。「Button.TouchUpInside += ……」(21行目)として、ボタンのイベントハンドラーを設定しているのが分かる。
自動生成されたPCLプロジェクトには、「MyClass.cs」ファイルがある。ここに簡単なコードを書いて、プラットフォームごとのプロジェクトから利用してみよう。
MyClassクラスに、次のコードのようにプロパティとメソッドを追加する。
using System;
namespace NativeUI
{
public class MyClass
{
public MyClass()
{
}
public int Count { get; private set; }
// Countをインクリメントするメソッド
public void CountUp() => Count++;
}
}
上のプロパティとメソッドを、プラットフォームごとのプロジェクトでボタンをクリックしたときに使うようにしよう(次からの3つのコード)。
……省略……
public class MainActivity : Activity
{
//int count = 1;
MyClass myClass = new MyClass();
protected override void OnCreate(Bundle bundle)
{
……省略……
button.Click += delegate
{
//button.Text = string.Format ("{0} clicks!", count++);
myClass.CountUp();
button.Text = $"{myClass.Count} clicks!";
};
}
}
……省略……
……省略……
public partial class ViewController : UIViewController
{
//int count = 1;
MyClass myClass = new MyClass();
……省略……
public override void ViewDidLoad()
{
……省略……
Button.TouchUpInside += delegate
{
//var title = string.Format ("{0} clicks!", count++);
//Button.SetTitle(title, UIControlState.Normal);
myClass.CountUp();
Button.SetTitle($"{myClass.Count} clicks!", UIControlState.Normal);
};
}
……省略……
……省略……
public sealed partial class MainPage : Page
{
//int count = 1;
MyClass myClass = new MyClass();
……省略……
protected override void OnNavigatedTo(NavigationEventArgs e)
{
……省略……
Button.Click += delegate
{
//var title = string.Format("{0} clicks!", count++);
//Button.Content = title;
myClass.CountUp();
Button.Content = $"{myClass.Count} clicks!";
};
……省略……
以上のように、共通のロジックを使うように変更した(ボタンクリックで数字がカウントアップされるという挙動は変わらない)。実行してみると、次のようになる。
ごく簡単な例ではあるが、ネイティブUIで共通のロジックを使う感触はつかんでいただけたかと思う。
Xamarin for Visual StudioでUIを構築する方法は2つある。Xamarin.Formsでは、Android/iOS/UWP全てに共通するUIを1つのXAMLで定義する。ネイティブUI(Xamarin Native)では、プラットフォームごとにそのプラットフォームの方法でUIを定義する。どちらも、ロジックのコードは共通のプロジェクトにC#で記述する。
今回は、Xamarin.Formsを詳しく解説し、また、ネイティブUIも簡単に試してみた。
Copyright© Digital Advantage Corp. All Rights Reserved.