ダイアログ (5) 日付の選択ダイアログ ================================================================================ 日付と時刻を選択するダイアログ。 それぞれ、DatePickerDialog と TimePickerDialog を使う。 また、日時を同時に指定するには、自分で、日付と時刻を選択するダイアログを作る必要 がある。これは、カスタムダイアログとして、AlertDialog を使う。このとき、カスタム ビューとしては、日付と時刻を選択するための DatePicker と TimePicker を組み合わせ て使う。 それぞれのサンプルは以下のとおり。 Dialog07 日付の選択ダイアログ Dialog071 日付の選択ダイアログで、タイトルの形式をカスタマイズ Dialog08 時刻の選択ダイアログ ※ Dialog09 日付と時刻の選択ダイアログが連続して設定 ※ Dialog091 日時の選択ダイアログ(カスタムダイアログ) ※ ※(6)で紹介 ■ 日付の選択ダイアログ 日付を選択するダイアログは、DatePickerDialog を使う。 とくに何もしなくても、タイトルや設定ボタン、キャンセル・ボタンなどは、日本語で表 示してくれる。 ただ、タイトルの形式は、次の形式で表示される。 土曜日, 8月 20, 2011 この形式の変更は、次のサンプル Dialog071 で補足する。 □ Dialog07Activity.java --- package jp.marunomaruno.android.sample; import java.util.Calendar; import android.app.Activity; import android.app.DatePickerDialog; import android.os.Bundle; import android.widget.DatePicker; import android.widget.TextView; public class Dialog07Activity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TextView date = (TextView) findViewById(R.id.date); Calendar calendar = Calendar.getInstance(); // (1) int year = calendar.get(Calendar.YEAR); int monthOfYear = calendar.get(Calendar.MONTH); int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); DatePickerDialog dialog = new DatePickerDialog(this, new DateSetHandler(date), year, monthOfYear, dayOfMonth); // (2) // dialog.setTitle(String.format(getString(R.string.date_format), calendar)); // (3) dialog.show(); } private class DateSetHandler implements DatePickerDialog.OnDateSetListener { // (4) private TextView date; public DateSetHandler(TextView date) { this.date = date; } @Override public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { // (5) Calendar calendar = Calendar.getInstance(); calendar.set(year, monthOfYear, dayOfMonth); date.setText(String.format(getString(R.string.date_format), calenda r)); // (6) } } } --- □ Calendar calendar = Calendar.getInstance(); // (1) ダイアログには、デフォルトで今日の日付を表示するので、Calendar.getInstance() で、 カレンダー日付のオブジェクトを設定する。 □ DatePickerDialog dialog = new DatePickerDialog(this, new DateSetHandler(date), year, monthOfYear, dayOfMonth); // (2) DatePickerDialog オブジェクトを生成する。 このとき、日付が設定されたときのリスナー、最初に表示される年・月・日を指定する。 ・クラス階層 java.lang.Object + android.app.Dialog + android.app.AlertDialog + android.app.DatePickerDialog ・コンストラクター --- DatePickerDialog(Context context, DatePickerDialog.OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth) DatePickerDialog(Context context, int theme, DatePickerDialog.OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth) --- □ // dialog.setTitle(String.format(getString(R.string.date_format), calendar)); // (3) コメントアウトされているが、setTitle() を使うことで、タイトルを設定する。ただし、 日付が変わったら、ここで指定した文字列は壊れ、デフォルトのタイトルの形式になる。 デフォルトのタイトルは、次の形式で表示される。 土曜日, 8月 20, 2011 これの形式を変更するのは、次に示すサンプル Dialog071 で示す。 □ private class DateSetHandler implements DatePickerDialog.OnDateSetListener { // (4) □ public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { // (5) ダイアログで日付を設定したときに呼び出されるリスナー DatePickerDialog.OnDateSetL istener を実装するクラスの定義。 DatePickerDialog.OnDateSetListener 日付を設定し終えて、設定ボタンをクリックしたときに呼ばれるリスナー・インターフ ェース。 つぎのメソッドを実装する。 abstract void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) 最終的に確定した日付が引数で受け取れる。ただし、monthOfYear は、Calendar クラス と同じで、0~11 の値でくる。 今回は、受け取ったテキストビューに、この日付を組み立てて設定している。 ※ --- このメソッドでは、引数 view から、設定されている日付を取得できるので、引数の year, monthOfYear, dayOfMonth はいらないと思うが、どうなんだろう。 単に使いやすさのためかな。 --- □ date.setText(String.format(getString(R.string.date_format), calendar));// (6) 最終的な日付をテキストビューに設定している。 形式は、リソース values/strings.xml で定義している。 内容は、以下のとおり。 <string name="date_format">%tF</string> これは、ISO 8601 format 形式で、以下の書式になる。 yyyy-mm-dd □ layout/main.xml --- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/date" /> </LinearLayout> --- □ values/strings.xml --- <resources> <string name="hello">Hello World, Dialog07Activity!</string> <string name="app_name">Dialog07</string> <string name="date_format">%tF</string> </resources> --- ■タイトルの形式をカスタマイズする 先のサンプル Dialog07 では、ダイアログのタイトルを表示する前に設定しても、日付を 変えると、タイトルの形式も変わってしまった。 タイトルの形式を変えないようにするには、DatePickerDialog を直接使うのではなく、 DatePicker をビューとしたカスタマイズのダイアログ(AlertDialog)として定義して使 う。 □ Dialog071Activity.java --- package jp.marunomaruno.android.sample; import java.util.Calendar; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Bundle; import android.util.Log; import android.widget.DatePicker; import android.widget.TextView; public class Dialog071Activity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TextView date = (TextView) findViewById(R.id.date); Calendar calendar = Calendar.getInstance(); int year = calendar.get(Calendar.YEAR); int monthOfYear = calendar.get(Calendar.MONTH); int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); DatePicker picker = new DatePicker(this); // (1) AlertDialog dialog = new AlertDialog.Builder(this) // (2) .setView(picker) // (3) .setTitle(String.format(getString(R.string.date_format), calendar)) // (4) .setPositiveButton(R.string.set_title, new DateSetHandler(picker, date)) // (5) .setNegativeButton(R.string.cancel_title, null) // (6) .show(); picker.init(year, monthOfYear, dayOfMonth, new DateChangedHandler(dialog)); // (7) Log.d("TEST", String.format("AlertDialog: %s", dialog.toString())); } private class DateChangedHandler implements DatePicker.OnDateChangedListener { // (8) private AlertDialog dialog; public DateChangedHandler(AlertDialog dialog) { this.dialog = dialog; } @Override public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) { // (9) Calendar calendar = Calendar.getInstance(); calendar.set(year, monthOfYear, dayOfMonth); Log.d("TEST", String.format("d: %tc", calendar)); dialog.setTitle(String.format(getString(R.string.date_format), calendar)); // (10) } } private class DateSetHandler implements DialogInterface.OnClickListener { // (11) private DatePicker picker; private TextView date; public DateSetHandler(DatePicker picker, TextView date) { this.picker = picker; this.date = date; } @Override public void onClick(DialogInterface dialog, int which) { // (12) Calendar calendar = Calendar.getInstance(); calendar.set(picker.getYear(), picker.getMonth(), picker.getDayOfMonth()); // (13) Log.d("TEST", String.format("c: %tc", calendar)); date.setText(String.format(getString(R.string.date_format), calendar)); } } } --- □ DatePicker picker = new DatePicker(this); // (1) 日付を選択するためのビューとして、DatePicker クラスを用いる。 ・クラス階層 java.lang.Object + android.view.View + android.view.ViewGroup + android.widget.FrameLayout + android.widget.DatePicker ・コンストラクター --- DatePicker(Context context) DatePicker(Context context, AttributeSet attrs) DatePicker(Context context, AttributeSet attrs, int defStyle) --- 自分自身の画面で使用するので、context は、自分自身(this)を用いる。 ・主なメソッド --- void init(int year, int monthOfYear, int dayOfMonth, DatePicker.OnDateChangedListener onDateChangedListener) --- □ AlertDialog dialog = new AlertDialog.Builder(this) // (2) DatePicker オブジェクトを乗せるための AlertDialog オブジェクトを生成する。 □ .setView(picker) // (3) カスタムビューとして、DatePicker オブジェクトを設定する。 □ .setTitle(String.format(getString(R.string.date_format),calendar)) // (4) ダイアログのタイトルを ISO 形式で設定する。リソースファイルで定義されているのは、 以下の形式である。 %tF □ .setPositiveButton(R.string.set_title, new DateSetHandler(picker, date)) // (5) 「設定ボタン」を設置する。ここでは、DialogInterface.OnClickListener を実装してい るオブジェクトをリスナーとして、ダイアログで設定した日付を表示するためのテキスト ビューを引数として渡している。 □ .setNegativeButton(R.string.cancel_title, null) // (6) 「キャンセル・ボタン」を設定する。 リスナー・オブジェクトは null になっているので、ボタンを押されたときは何もしない。 □ picker.init(year, monthOfYear, dayOfMonth, new DateChangedHandler(dialog)); // (7) DatePicker オブジェクトを初期化する。 引数は、最初に出したい日付(年・月・日)、日付が変化したときに動作するリスナーのオ ブジェクト。 今回は、日付が変わったときに、ダイアログのタイトルも変更したいので、リスナーには、 ダイアログのオブジェクトを渡している。 □ private class DateChangedHandler implements DatePicker.OnDateChangedListener { // (8) 引数は、最初に出したい日付(年・月・日)、日付が変化したときに動作するリスナーを定 義。このオブジェクトは、DatePicker.OnDateChangedListener インターフェースを実装 する。 DatePicker.OnDateChangedListener 日付の選択で、日付が変わったことに対するバンドラーを定義するリスナー・インターフ ェース。 ・メソッド --- abstract void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) --- 設定ボタンが押されたときは、これは動作しない。したがって、まったく日付を変える必 要がない場合は、設定ボタンのリスナーで、日付を設定する必要がある。 □ public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) { // (9) ダイアログで日付が変わったことに対するハンドラー・メソッド。 □ dialog.setTitle(String.format(getString(R.string.date_format), calendar)); // (10) ダイアログで日付が変わったら、その日付をタイトルに設定している。 タイトルの形式は、ISO 形式として、リソースに設定している。 □ private class DateSetHandler implements DialogInterface.OnClickListener { // (11) □ public void onClick(DialogInterface dialog, int which) { // (12) 設定ボタンがクリックされたことに対するリスナーのクラスとハンドラー・メソッドを定 義する。(「ダイアログ (1)」を参照) □ calendar.set(picker.getYear(), picker.getMonth(), picker.getDayOfMonth()); // (13) DatePicker オブジェクトを受け取っているので、そこから日付を取得して設定する。 □ values/strings.xml --- <resources> <string name="hello">Hello World, Dialog071Activity!</string> <string name="app_name">Dialog071</string> <string name="set_title">設定</string> <string name="cancel_title">キャンセル</string> <string name="date_format">%tF</string> </resources> --- 以上