DatePickerDialogのカスタマイズとカレンダーの表示
今度は、DatePickerDialogを少しカスタマイズしてみましょう。DatePickerDialogの実態は、android.app.AlertDialogクラスに、ビューとしてandroid.widget.DatePickerを設定したものです。AlertDialog.Builderクラスを使って、同じようなコンポーネントを組み立てることができます。
次のサンプルでは、年と日付を選択するダイアログを表示し、選択されると、該当の月のカレンダーを表示するものです。
// 年と日を選択するダイアログの表示
public void sampleUI2() {
// AlertDialog.Builderを生成
AlertDialog.Builder builder = new AlertDialog.Builder(this);
// DatePickerを生成(デフォルトで現在日時に設定される)
final DatePicker datePicker = new DatePicker(this);
// ViewにDatePickerを設定
builder.setView(datePicker);
// タイトルを設定
builder.setTitle("年と月を選択してください");
// 設定ボタンを設定 -----------------------------------------------(1)
builder.setPositiveButton("カレンダー表示",
new DatePickerDialog.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
printCalendar(datePicker.getYear(),
// カレンダーの表示
datePicker.getMonth());
}
});
// AlertDialogを生成
AlertDialog alertDialog = builder.create();
// 日のパーツを非表示にする --------------------------------------(2)
ViewGroup datePickerGroup = (ViewGroup) datePicker.getChildAt(0);
datePickerGroup.getChildAt(2).setVisibility(View.GONE);
// AlertDialogを表示
alertDialog.show();
}
// カレンダーの表示
public void printCalendar(int y, int m) {
printString(y + "年" + (m + 1) + "月のカレンダー");
// 指定の月の初日を設定する
Calendar cal = Calendar.getInstance();
cal.set(y, m, 1);
// 2桁で日を表示する
SimpleDateFormat sdf = new SimpleDateFormat("dd ");
// 月の最終日の取得 ---------------------------------------------(3)
int max = cal.getActualMaximum(Calendar.DATE);
// 月初の曜日の取得
int w = cal.get(Calendar.DAY_OF_WEEK);
String wstr = "";
// 第1週の空白を出力する
for (int i = 0; i < w - 1; i++) {
wstr += " ";
}
int last = 0;
// 1週間の表示
do {
for (int i = 0; i < 8 - w; i++) {
wstr += sdf.format(cal.getTime());
// 月の最終日か?
if (max == cal.get(Calendar.DATE)) {
last++;
break;
}
// 1日加算 ---------------------------------------------(4)
cal.add(Calendar.DAY_OF_MONTH, 1);
}
printString(wstr);
w = 1;
wstr = "";
} while (last == 0);
}
コメントを追えば処理の流れは理解できるでしょう。ここでは、ポイントをしぼって解説することにします。
(1)では、ダイアログに表示されるボタンを設定しています。ボタンに表示される文字列と、ボタンがクリックされたときのイベントリスナーを指定します。選択された年と日は、DatePickerクラスのgetYear、getMonthメソッドで取得しています。
(2)では、日を選択するパーツを非表示にしています。年と月だけを選択したいので、日の選択は不要なのですが、個別に設定できないため、setVisibilityメソッドを使って日を選択するビューを非表示にしています。
DatePickerクラスには、このビューを特定するメソッドが見当たらないので、getChildAtメソッドで、3番目を指定しています。年、月、日とパーツが並ぶために、日にあたるgetChildAt(2)を指定しています。ただしこのパーツの並びは、SimpleDateFormatクラスのtoPatternメソッドで得られるデフォルトのパターンに従っています。そのため、例えば米国のロケールであれば、パターンは"M/d/yy"となり、日は2番目になります。つまりgetChildAt(1)とする必要があるのですが、今回のサンプルではそこまでは考慮していません。
カレンダーを表示する部分の(3)では、指定の月の最終日(28、30、31など)と、その月の初日の曜日を取得しています(1週目の表示のため)。
カレンダーの日の表示は、Calendarオブジェクトを1日ずつ進めて、その値を表示しています。(4)で、Calendarクラスのaddメソッドを利用し、1日を加算しています。
最後に
Android開発のためのJava SE再入門も今回が最後となりました。このところのスマートフォンバブルは驚くばかりです。Androidアプリ開発者も忙しい日々をお送りのことかと思います。そんなアプリ開発にかかわる皆様に、この連載記事が少しでもお役に立つことができれば幸いです。
参考資料
- 『JAVAポケットリファレンス』 高江賢 著、山田祥寛 監修、技術評論社、2011年3月
- Java Platform, Standard Edition 6 API 仕様
- Android Developers
