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