Xamarin 逆引きTips
Xamarin.iOSで画面をレイアウトするには?(Xcode利用/ビルトインiOS用UIデザイナー)
iOS用の画面レイアウトを、Xcodeで行う方法を解説。また、Xamarin StudioのビルドインUIデザイナーで行う方法も説明する。
Xamarin.iOSでの画面のレイアウトについては、先日大きな進展があった。これまでレイアウト作成作業はXcodeに委譲する形であったが、Xamarin Studio自体にiOS用のUIデザイナーが搭載されたのだ。
とはいえ、この機能はまだ初期状態でONになっていないため、本Tipsでは、「従来からのXcodeを利用する方法」と「Xamarin StudioのビルドインUIデザイナー」の両方について説明する。
いずれの場合も、Xamarin.iOSで画面レイアウトを行うには、Macが必要になる。このTipsは、Mac上でXamarin Studio(5/15時点の最新版)を利用することを前提としているので注意してほしい。
画面に関連するファイル群
まずは、Xamarin.iOSのプロジェクトを作成し、その構成ファイルを見ていこう。図1は、[iOS]-[iPhone]-[Single View Application]で(「HelloWorld」という名前で)プロジェクトを作成した直後のファイルツリーである。
1HelloWorldViewController.cs
iOSにおける画面(ViewController)の実装クラスである。下記のようなUIViewController
クラスから派生したコードとなっており、ネイティブの開発者には見慣れたメソッドが並んでいるのが分かるだろう。
……省略……
public partial class HelloWorldViewController : UIViewController
{
public HelloWorldViewController(IntPtr handle) : base(handle)
{
}
……省略……
public override void ViewDidLoad()
{
base.ViewDidLoad();
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
}
……省略……
}
|
2HelloWorldViewController.designer.cs
Xamarin Studioによって自動的に生成されるファイルだ。このファイルは開発者が改変してはいけない。参考までに(UIレイアウト後との比較のために)現時点でのファイルの内容を下記に示しておく。
// This file has been generated automatically by MonoDevelop to store outlets and
// actions made in the Xcode designer. If it is removed, they will be lost.
// Manual changes to this file may not be handled correctly.
//
using MonoTouch.Foundation;
namespace HelloWorld
{
[Register("HelloWorldViewController")]
partial class HelloWorldViewController
{
void ReleaseDesignerOutlets()
{
}
}
}
|
3MainStoryboard.storyboard
画面のレイアウトを定義したファイル。Xamarin.Androidにおけるactivity_main.xml
とMain.axml
の関係と同じく、iOSのネイティブ開発(以下、「ネイティブ」と表記)で使用するファイルと同一仕様のファイルだ。
Xcodeによる画面レイアウト
[MainStoryboard.storyboard]をダブルクリックなどで実行すると、既定の動作ではXcodeが別途起動する。Xamarin Studioは、Xcodeでのファイルの変更を監視し、HelloWorldViewController.designer.cs
に必要なコードを自動追加する。その動きを見てみよう。
1MainStoryboard.storyboardをダブルクリックしてXcode(のInterface Builder)を起動する
図2のようにXcodeが別アプリとして起動する。
Interface Builderの左サイドバーにある[Hello World View Controller]を選択して、右上のアイコン(=[Show the identity inspector])をクリックしてみよう。すると[Custom Class]に「HelloWorldViewController」と表示されており、このビューコントローラーとHelloWorldViewControllerが関連付いていることが確認できる。
2Interface Builderで画面をレイアウトする
画面上にテキスト入力用のテキストフィールドと、ボタンを追加してみよう。右下のビューから、[Text Field]と[Button]を画面上にドラッグ&ドロップする。ボタンのタイトルは「Enter」にでも変更しておこう(※ボタン部分をクリックするか、図3のように右上のアイコンで[Attributes Inspector]を開いて、その[Title]欄で編集できる)。
3テキストフィールドとボタンのアウトレットを作成する
次に、画面左端のProject Navigatorから、[HelloWorldViewController.h]を、[Option]キーを押しながらマウスでクリックする。すると下図のように、Interface BuilderとHelloWorldViewController.h
が横並びに表示される。右側のサイドバーが邪魔な場合はツールバーのアイコンで非表示にできる。
この状態で、Interface BuilderのテキストフィールドをControlキーを押しながらHelloWorldViewController.h
の@end
の前にドラッグ&ドロップする(図5)。
ドロップ後表示されるポップアップで[Connection]を「Outlet」、[Name]を「textMyNumber」として、[Connect]ボタンを押す。
ボタンに対しても同じ手順で[Name]を「buttonEnter」としてアウトレットを作成すると、HelloWorldViewController.h
ファイルは以下のようになる。
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface HelloWorldViewController : UIViewController {
}
@property (retain, nonatomic) IBOutlet UITextField *textMyNumber;
@property (retain, nonatomic) IBOutlet UIButton *buttonEnter;
@end
|
Command+Sキーでプロジェクトを保存したら、Xamarin Studioに戻ろう。Xcodeはそのまま放置しても、閉じても構わない。
4Xamarin StudioとXcodeの同期の結果を確認する
Xamarin Studioに戻ったら、HelloWorldViewController.designer.cs
ファイルを開いてみよう。以下のように、Xcodeで作成したアウトレットがC#のコードとして再現されているはずだ(反映されていない場合、同期が失敗しているので、Xcodeで保存し直したり、Xcodeを終了したりしてみよう)。
// WARNING
//
// This file has been generated automatically by Xamarin Studio to store outlets and
// actions made in the UI designer. If it is removed, they will be lost.
// Manual changes to this file may not be handled correctly.
//
using MonoTouch.Foundation;
using System.CodeDom.Compiler;
namespace HelloWorld
{
[Register ("HelloWorldViewController")]
partial class HelloWorldViewController
{
[Outlet]
MonoTouch.UIKit.UIButton buttonEnter { get; set; }
[Outlet]
MonoTouch.UIKit.UITextField textMyNumber { get; set; }
void ReleaseDesignerOutlets ()
{
if (textMyNumber != null) {
textMyNumber.Dispose ();
textMyNumber = null;
}
if (buttonEnter != null) {
buttonEnter.Dispose ();
buttonEnter = null;
}
}
}
}
|
これで、Xamarin.iOS側でもアウトレットが使用できることが分かる。あとはHelloWorldViewController.cs
ファイルで、これらを使って処理を実装するだけだ。
5Viewを利用するコードを記述する
HelloWorldViewController.cs
ファイルのViewDidLoad
メソッドに以下のように実装する。
public override void ViewDidLoad()
{
base.ViewDidLoad();
buttonEnter.TouchUpInside += (s, e) =>
{
var alertView = new UIAlertView(string.Empty, textMyNumber.Text,
null, "Close", null);
alertView.Show();
};
}
|
Xamarin.iOSもdelegateを使用するAPIは可能な限りイベントになっている。上記のコードでは、TouchUpInside
がそれだ。ネイティブのObjective-C言語では、delegateによるコールバックはたいていの場合、別のメソッドに分離して記述する必要があり、「ボタンAを押した時の処理」という関連が分かりにくい。Xamarin.iOSの「イベント+ラムダ式」による記述は、アクションとコールバックの関連が視認でき、またイベントハンドラーのスコープが最小に保てるため、見やすく保守のしやすいコードとなる。
出来上がったプログラムを実行すると、図7のようになる。
Xamarin StudioのiOSデザイナーによる画面レイアウト
続いて、新たにXamarin Studioに搭載されたiOSデザイナーを使った画面レイアウトを行う方法を説明する。
1iOSデザイナーを有効にする
[システムメニュー]-[Preference]-[プロジェクト]-[iOS]より[Enable experimental iOS Designer]にチェックを入れる。なお、experimentalを冠している通り、この機能はまだ実験的なものであることに注意が必要だ(筆者が試した範囲では十分に実用できるものであったが)。
2iOSデザイナーを起動する
Xamarin Studioで[MainStoryboard.storyboard]をダブルクリックすると、iOSデザイナーが起動する(ちなみにマウスの右クリックをすることで、従来どおりXcodeも起動できる)。
見ての通り、Interface Builderとよく似たルック&フィールになっている。また、先ほどInterface Builderで作成したレイアウトも正しく反映されており、相互利用が可能であることが分かる。
3iOSデザイナーで画面をレイアウトする
テキストフィールドとボタンが配置されている画面に、さらにラベルを追加してみよう。Interface Builderと同じように右上のToolboxから「Label」を画面上にドラッグ&ドロップする。
次に、追加したラベルの名前を設定する(Interface Builderのアウトレットを作る手順に相当する)。追加したラベルを選択して、右下の[プロパティ]パッドの[Name]に「lableMyNumber」と入力してEnterキーを押そう(図11)。
これでHelloWorldViewController.designer.cs
ファイルにlableMyNumber
が生成されたはずだ。Interface Builderを使う方法に比べて、ずいぶん手順が簡単になっている。
4Viewを利用するコードを記述する
あとはラベルを使った実装をするだけだ。HelloWorldViewController.cs
ファイルのViewDidLoad
メソッドの実装を以下のように変更してみよう。
public override void ViewDidLoad()
{
base.ViewDidLoad();
buttonEnter.TouchUpInside += (s, e) =>
labelMyNumber.Text = "Your number is " + textMyNumber.Text;
}
|
このコードを実行すると、図12のようになる。
まとめ
今回は、Xamarin.iOSで画面レイアウトを、Xcode(Interface Builder)で行う手順と、Xamarin StudioのiOSデザイナーで使う手順を解説した。
Xcodeに慣れている開発者は前者を、そうでない開発者は後者を使うとよいだろう。ただし、Xamarin StudioのiOSデザイナーはまだ実験段階の機能なので、その旨、了解して利用する必要がある。アウトレットの作成などはXamarin Studioを使った方が、圧倒的に手順が少ないので、早く正式版となることを期待したい。
今回は簡単な画面レイアウトしか行わなかったが、Xamarin StudioがXcodeを完全に代替できるかは現時点では未知数だ。iOSデザイナー機能の詳細は、Xamarin Developer Centerの「iOS Designer Overview(英語)」で確認してほしい。
iOSデザイナーは、XamarinのVisual Studioアドインにも搭載される見込みであるようなので、Windowsを主に使う開発者は待ち遠しいだろう。アルファ版ならすぐに試すことができるようだ。
【コラム】XIBについて
iOSでの画面レイアウト定義ファイルは.xib
ファイルも存在する。Xamarin.iOSのプロジェクト作成テンプレートの中には、これを使用するものは用意されていないようだが、プロジェクトに.xib
を追加する方法は用意されている。
追加するにはプロジェクトを開いた状態で、[ファイル]-[新規]-[ファイル]-[iOS]から「Empty iPhone Interface Definition」を選択する。作成された.xib
ファイルはXcodeで開くことができるが、Xamarin StudioのiOSデザイナーは対応していないようだ。
次回は、画面遷移について解説する予定だ。
※以下では、本稿の前後を合わせて5回分(第1回~第5回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
1. Xamarin.Android/Xamarin.iOSを利用するには?
C#でAndroid/iOSアプリを開発できるXamarinの実践TIPSの連載がスタート。TIPSの方向性や読者対象を示し、Xamarinの概要やインストールについて解説する。
2. Xamarin.Androidで画面をレイアウトするには?
Xamarin.Androidでの画面のレイアウトの仕組みは、ネイティブのAndroidとほぼ同じ。そのレイアウト方法をネイティブでの手順と比較しながら解説する。
3. 【現在、表示中】≫ Xamarin.iOSで画面をレイアウトするには?(Xcode利用/ビルトインiOS用UIデザイナー)
iOS用の画面レイアウトを、Xcodeで行う方法を解説。また、Xamarin StudioのビルドインUIデザイナーで行う方法も説明する。
4. Xamarin.Androidで画面遷移を行うには?
Xamarin.Androidで画面を追加する方法と、2つの画面間を遷移し、遷移先にデータを渡す方法、遷移先から返り値を得る方法を解説する。
5. iOS/Androidの画面レイアウトを共通化するには?(Xamarin.Forms)
Xamarin 3がリリースされた。その新機能として注目されるXamarin.Formsの概要と、基本的な使い方、メリット/デメリットを解説する。Xamarin.Formsを使ってiOS/Android/Windows Phone間で画面レイアウトも共通化しよう。