Xamarin逆引きTips
Xamarin.Androidで画面をレイアウトするには?
Xamarin.Androidでの画面のレイアウトの仕組みは、ネイティブのAndroidとほぼ同じ。そのレイアウト方法をネイティブでの手順と比較しながら解説する。
Xamarin.Androidでの画面のレイアウトは、ネイティブのAndroidとほとんど同じ仕組みだ。これは、前回説明した通り、XamarinのAPIは、View関連については各プラットフォームのAPIのラッパーであるためだ。
今回は、ネイティブAndroid(以下、「ネイティブ」と記載)での手順と比較しながら、Xamarin.Androidで画面レイアウトを行う方法を解説する。
画面に関連するファイル群
まずは、Xamarin StudioでXamarin.Androidのプロジェクトを作成した直後のファイルツリーを見てみよう。
読者がAndroid開発者なら、見慣れたディレクトリやファイルが並んでいることが分かるだろう。ただし命名は、.NETの文化に習って「アッパーキャメルケース」だ。
以下、代表的なファイルについて解説する。
1AndroidManifest.xml
これはAndroidアプリケーションのメタ情報を記述するためのファイルである。Xamarin.Androidで作成されるファイルの内容は、以下のようになっている。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="HelloWorld.HelloWorld">
<uses-sdk />
<application android:label="HelloWorld">
</application>
</manifest>
|
ネイティブでのAndroidManifest.xml
ファイルと同じ仕様であるが、画面に関する記述(=<activity/>~</activity>
)が一切ないことに気付くだろう。Xamarin.Androidでは、画面に関するメタ情報は、実装クラス(例:MainActivity
)の属性として記述する。
ネイティブAndroidでは、「画面のクラスは追加したが、AndroidManifest.xmlファイルに追記し忘れたために、画面が表示されない」というミスを起こす可能性があった。だが、Xamarin.Androidではその心配はない(ネイティブでもIDEの進化により、このようなミスはだいぶ減ってはいるが)。
2MainActivity.cs
画面の実装クラスであるMainActivity.cs
ファイルのコードは次のようになっている。
1
2
3
4
|
[Activity(Label = "HelloWorld", MainLauncher = true)]
public class MainActivity : Activity
{
int count = 1;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
Button button = FindViewById<Button>(Resource.Id.myButton);
button.Click += delegate
{
button.Text = string.Format("{0} clicks!", count++);
};
}
}
|
1で、1で説明した画面に関するメタ情報の定義を行っている。ここではActivityのタイトルと、起動時に表示すること示すMainLauncher=true
を設定している。設定可能な属性の情報は、Xamarin Developer Centerの「Working with AndroidManifest.xml(英語)」を参考にしてほしい。
2で、画面のレイアウト情報を設定している。ネイティブではsetContentView(R.layout.activity_main)
と記述するところだ。R
からResource
に、layout
がLayout
に変わっているだけだ。
3では、レイアウトに定義したView(ここではButtonウィジェット)のインスタンスを得ている。これもネイティブとほぼ同じだ。
4では、ボタンが押された時の処理を記述している。これはXamarinの特徴的なところで、ネイティブでsetOnClickListener
などのリスナークラスを設定するAPIは、可能な限り、このような.NET Frameworkの「イベント」に置き換えられている。これにより複数のハンドラーを設定できたり、Javaに比べて簡潔な記述が可能になったりしている。
3と4は、C#のコードとしてはまだ少し冗長で、以下のように短縮できる。
3
4
|
var button = FindViewById<Button>(Resource.Id.myButton);
button.Click += (s, e)
=> button.Text = string.Format("{0} clicks!", count++);
|
ローカル変数は、型を指定しなくてもvar
キーワードを置くことで右辺より型が自動的に推測される。イベントハンドラーは、ラムダ式を利用すれば、1行で簡潔に書ける。このような言語機能は、Xamarinを採用する大きなメリットの1つであるので積極的に活用していきたい。
3Main.axml
これは画面のレイアウトを記述したファイルだ。ネイティブで利用するXMLファイル(例:activity_main.xml
)ファイルと全く同じ仕様のファイルである。そのため、ほとんどの場合で、ネイティブで利用していたものがXamarin.Androidでもそのまま使用できるだろう。ただしファイルの拡張子が.axml
となる(一見、XAML(ザムル)と間違えるが全くの別物だ)。
画面レイアウトの方法
.axml
ファイルをダブルクリックすると、図2のようなUIデザイナーが起動する。
Android用のUIデザイナーとXMLのコードエディターが、画面下部の[コンテンツ]/[ソース]タブで切り替えられる。
ネイティブのEclipse+ADTに搭載されるUIデザイナーと似たルック&フィールになっているので、それほど戸惑わずに利用できるだろう。ここでは基本的な使い方についてのみ説明する。
1Toolboxから追加したいViewを画面上にドラッグ&ドロップする
試しに、入力可能なテキスト要素である[Text Fields]グループ内の[Plain Text]を画面上の[Hello World]ボタンの下に配置してみよう(図3)。
Main.axml
ファイルのルート要素は、<LinearLayout>
のorientation=vertical
になっているので、要素は縦に並ぶ。ドラッグ中に、どこにViewが挿入されるかが青線で示されるのですぐに分かるだろう。追加すると以下のような画面となる。
このときのMain.axml
ファイルは、以下のようになっている。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/myButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/editText1" />
</LinearLayout>
|
[Plain Text]をドラッグ&ドロップして配置した結果、
2Viewの属性を設定する
追加した<EditText>要素の属性を、[プロパティ]ウィンドウで次のように変更してみよう。
- [Id]: @+id/editMyNumber
- [Hint]: Input your number
- [Input Type]: number
変更後、UIデザイナーとMain.axml
ファイルは、以下のように変わっているはずだ。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:id="@+id/myButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<EditText
android:id="@+id/editMyNumber"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Input your number"
android:inputType="number" />
</LinearLayout>
|
【コラム】レイアウトにおけるリテラルの使用について
この例ではHint属性にリテラル文字列を直接指定しているが、このようなリテラル値はStrings.xml
やColors.xml
といったリソースファイルに定義し、その参照を利用すべきである。
3Viewを利用するコードを記述する
ボタンを押した時に、入力した数値をToastで表示する機能を実装してみよう。
[Activity(Label = "HelloWorld", MainLauncher = true)]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
var editMyNumber = FindViewById<EditText>(Resource.Id.editMyNumber);
var button = FindViewById<Button>(Resource.Id.myButton);
button.Click += (s, e) =>
{
Toast.MakeText(this, "Your number is " + editMyNumber.Text, ToastLength.Short).Show();
};
}
}
|
.axml
ファイルでEditTextに追加した際に設定したID editMyNumber
を指定してFindViewById
メソッドを呼び出すと、EditTextのインスタンスが取得できる。あとはボタンが押された時のコードを少し修正して、Toastを表示している。
このサンプルを動作させると図6のようになる。
まとめ
Xamarin.AndroidのUIデザイナーを使って、Viewを追加し、それをコードから利用する例を紹介した。UIデザイナーは、機能はもっと豊富なので、詳しい使い方はXamarin Developer Centerの「Designer Overview(英語)」を見てほしい。
また、このUIデザイナーは完成度の高い機能ではあるものの、本家であるEclipse+ADTやAndroid StudioのUIデザイナーと比べると若干の見劣りを感じることもあるだろう。その場合は、画面レイアウト作成はネイティブのツールで行い、出来上がったXMLファイルをXamarin.Androidで使用することもできる。実際、筆者がUIレイアウトを行う際は、UIデザイナーよりもXMLコードをじか書きすることに慣れているが、Xamarin.AndroidのXMLコードエディターよりも、Eclipse+ADTの方が、入力補完がよく利くので多用している。
Viewを使うコードも、ネイティブとほとんど変わりがないが、C#/.NET Frameworkの機能を生かして、より簡潔な記述ができるので、ぜひ使ってみてほしい。
【コラム】Fragmentについて
最近のネイティブの開発では、「Fragment」と呼ばれる「View要素をグループ化して別部品にする機能」を使うことが推奨されており、Eclipse+ADTでAndroidプロジェクトを作成すると、Fragmentを使用するコードが生成されるようになった。
このため、単純な“HelloWorld”アプリでも、ネイティブとXamarin.Androidでは構成に違いが見られるので注意してほしい。具体的には、Activityのレイアウトとして行っていたものは、Fragmentのレイアウトとなり、そのFragmentをActivityが読み込む形になっている。
レイアウトファイルの仕様に変更はないので、Fragmentのレイアウト作成にもXamarin.AndroidのUIデザイナーは利用可能である。この辺りは、Fragmentを利用するTipsの回で述べたいと思う。
次回は、Xamarin.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間で画面レイアウトも共通化しよう。