AlertDialog.BuilderとLayoutInflaterによりダイアログにレイアウトを流し込む
AndroidのDialogクラスの派生クラスは、内部のBuiderクラスを使うことによりダイアログを様々にカスタマイズすることが可能だ。
SDKに添付されてくるAlertDialogSamples.javaには様々なダイアログの例が実際に動く例として公開されている。
- AlertDialogSamples.java
protected Dialog onCreateDialog(int id) { switch (id) { case DIALOG_YES_NO_MESSAGE: return new AlertDialog.Builder(AlertDialogSamples.this) .setIcon(R.drawable.alert_dialog_icon) .setTitle(R.string.alert_dialog_two_buttons_title) .setPositiveButton(R.string.alert_dialog_ok , new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { } }) .setNegativeButton(R.string.alert_dialog_cancel , new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { } }) .create();
メソッドチェインにより、一行でダイアログを構成しており、最後のcreateメソッドによりダイアログを実体化している。
Builderは一般的なビューを直接配置してイベントハンドラを割り当てることすらできるため、これらを使うことでかなりの要件を満たすことが可能だが、場合によってはユーザ側が用意したビュー(レイアウト)をそのままダイアログ上に流し込むことが必要になるケースもあるだろう。
そんな場合でもAlertDialog.Builder#setViewメソッドを使用して、レイアウト上に生成したビュー全体をダイアログに流し込むことができる。
拙作のCalendarViewでは、年月が表示されているヘッダ部分をタッチすることで、ダイアログから表示対象の年月を直接入力することができる。(以前に言及したように、DatePickerは日が邪魔で使えなかった)
ダイアログ上の+ボタンと年、月を表示するEditText、-ボタンは外部レイアウトXMLにより構成されており、ダイアログが表示される直前にインフレータにより実体化される。
- CalendarView.java
//コンテキストからインフレータを取得 LayoutInflater inflater = LayoutInflater.from(this.getContext()); //レイアウトXMLからビュー(レイアウト)をインフレート final View yearMonthView = inflater.inflate(R.layout.layout_yearmonth, null); //ダイアログを構成 AlertDialog.Builder builder = new AlertDialog.Builder(this.getContext()); builder.setTitle(res.getString(R.string.YEAR_MONTH_DIALOG_TITLE)) .setCancelable(true) .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //OKボタンが押下された時に入力された年月をビューに設定する } }) .setView(yearMonthView) .show(); //ダイアログ表示
流し込むレイアウトは通常のActivityで扱うものと全く同じであれ、Eclipse ADTのレイアウトエディタで作成、編集できる。
- layout_yearmonth.xml (レイアウトエディタ)
この方法だとどんなビュー・レイアウトでもダイアログで利用できる訳で、全く持って素晴らしい。今まで数々のGUIツールキットでいろいろなダイアログのためのAPIを見てきたが、これだけの完成度の高い(柔軟性、生産性)ものはあまり見たことがない。