Android Time Picker
ユーザーが時刻を選択する方法を提供するには、TimePicker を使用できます。 Android アプリでは、通常、時刻値を選択するために TimePicker
と TimePickerDialog を合わせて使用します。これは複数のデバイスやアプリケーションにわたって一貫性のあるインターフェイスを確保するのに役立ちます。 TimePicker
を使用すると、ユーザーは 24 時間制または 12 時間制の AM/PM モードで 1 日の中の時刻を選択できます。
TimePickerDialog
は、TimePicker
をダイアログ内にカプセル化するヘルパー クラスです。
概要
現代的な Android アプリケーションでは、TimePickerDialog
を DialogFragment 内に表示します。 これにより、アプリケーションは TimePicker
をポップアップ ダイアログとして表示したり、アクティビティ内に埋め込んだりできます。 さらに、DialogFragment
はダイアログのライフサイクルと表示を管理し、実装する必要があるコードの量を減らします。
このガイドでは、TimePickerDialog
を DialogFragment
の中にラップされた状態で使用する方法を示します。 サンプル アプリケーションでは、ユーザーがアクティビティ上のボタンをクリックすると、モーダル ダイアログとして TimePickerDialog
が表示されます。 時刻がユーザーによって設定されると、ダイアログが終了し、ハンドラーは選択された時刻を使用してアクティビティ画面上の TextView
を更新します。
要件
このガイドのサンプル アプリケーションは Android 4.1 (API レベル 16) 以上を対象としていますが、Android 3.0 (API レベル 11 以上) でも使用できます。 Android Support Library v4 をプロジェクトに追加し、いくつかのコードを変更することで、古いバージョンの Android をサポートすることが可能です。
TimePicker の使用
この例では DialogFragment
を拡張し、DialogFragment
のサブクラス実装 (以下では TimePickerFragment
と呼びます) で TimePickerDialog
をホストし表示します。 サンプル アプリは、初期起動時に、選択された時刻を表示するために使用される TextView
の上に、以下のように [PICK TIME] ボタンを表示します。
[PICK TIME] ボタンをクリックすると、次のスクリーンショットに示すようにサンプル アプリが TimePickerDialog
を起動します。
TimePickerDialog
において、時刻を選択し [OK] ボタンをクリックすると、TimePickerDialog
によって IOnTimeSetListener.OnTimeSet というメソッドが起動されます。
このインターフェイスは、ホスティング DialogFragment
(以下で説明される TimePickerFragment
) によって実装されます。 [キャンセル] ボタンをクリックすると、フラグメントとダイアログが閉じます。
DialogFragment
は、以下の 3 つの方法のいずれかで、選択された時刻をホスティング アクティビティに返します。
メソッドの呼び出しまたはプロパティの設定 – アクティビティは、この値を設定するためのプロパティまたはメソッドを提供できます。
イベントの発生 –
DialogFragment
はOnTimeSet
が呼び出されたときに発生するイベントを定義できます。Action
の使用 –DialogFragment
はAction<DateTime>
を呼び出して、アクティビティに時刻を表示できます。 アクティビティは、DialogFragment
のインスタンスを作成するときにAction<DateTime
を提供します。
このサンプルでは、3 番目の手法を使用します。これには、アクティビティが DialogFragment
に対して Action<DateTime>
ハンドラーを提供することが必要です。
アプリ プロジェクトを開始する
TimePickerDemo という名前の新しい Android プロジェクトを開始します (Xamarin.Android プロジェクトの作成に慣れていない場合は、「Hello, Android」を参照して、新しいプロジェクトを作成する方法を確認してください)。
Resources/layout/Main.axml を編集し、その内容を次の XML に置き換えます。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:padding="16dp">
<Button
android:id="@+id/select_button"
android:paddingLeft="24dp"
android:paddingRight="24dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="PICK TIME"
android:textSize="20dp" />
<TextView
android:id="@+id/time_display"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:paddingTop="22dp"
android:text="Picked time will be displayed here"
android:textSize="24dp" />
</LinearLayout>
これは、時刻を表示する TextView と TimePickerDialog
を開く Button を持つ基本的な LinearLayout です。 このレイアウトでは、アプリをより簡単かつ理解しやすくするために、ハードコーディングされた文字列とディメンションを使用しています。運用アプリでは通常、(DatePicker のコード例で確認できるように) これらの値にはリソースを使用します。
MainActivity.cs を編集し、内容を次のコードに置き換えます。
using Android.App;
using Android.Widget;
using Android.OS;
using System;
using Android.Util;
using Android.Text.Format;
namespace TimePickerDemo
{
[Activity(Label = "TimePickerDemo", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
TextView timeDisplay;
Button timeSelectButton;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
timeDisplay = FindViewById<TextView>(Resource.Id.time_display);
timeSelectButton = FindViewById<Button>(Resource.Id.select_button);
}
}
}
この例をビルドして実行すると、次のスクリーンショットのような初期画面が表示されるはずです。
TimePicker
を表示するための DialogFragment
がまだ実装されていないため、[PICK TIME] ボタンをクリックしても何も起こりません。
次の手順では、この DialogFragment
を作成します。
DialogFragment の拡張
TimePicker
で使用するために DialogFragment
を拡張するには、DialogFragment
から派生した TimePickerDialog.IOnTimeSetListener
を実装するサブクラスを作成することが必要です。 次のクラスを MainActivity.cs に追加します。
public class TimePickerFragment : DialogFragment, TimePickerDialog.IOnTimeSetListener
{
public static readonly string TAG = "MyTimePickerFragment";
Action<DateTime> timeSelectedHandler = delegate { };
public static TimePickerFragment NewInstance(Action<DateTime> onTimeSelected)
{
TimePickerFragment frag = new TimePickerFragment();
frag.timeSelectedHandler = onTimeSelected;
return frag;
}
public override Dialog OnCreateDialog (Bundle savedInstanceState)
{
DateTime currentTime = DateTime.Now;
bool is24HourFormat = DateFormat.Is24HourFormat(Activity);
TimePickerDialog dialog = new TimePickerDialog
(Activity, this, currentTime.Hour, currentTime.Minute, is24HourFormat);
return dialog;
}
public void OnTimeSet(TimePicker view, int hourOfDay, int minute)
{
DateTime currentTime = DateTime.Now;
DateTime selectedTime = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, hourOfDay, minute, 0);
Log.Debug(TAG, selectedTime.ToLongTimeString());
timeSelectedHandler (selectedTime);
}
}
この TimePickerFragment
クラスについては、次のセクションで小さいパーツに分けて説明します。
DialogFragment の実装
TimePickerFragment
では、ファクトリ メソッド、Dialog インスタンス化メソッド、TimePickerDialog.IOnTimeSetListener
が必要とする OnTimeSet
ハンドラー メソッドなど、いくつかのメソッドを実装します。
TimePickerFragment
はDialogFragment
のサブクラスです。 また、以下のようにTimePickerDialog.IOnTimeSetListener
インターフェイスも実装します (つまり、必要なOnTimeSet
メソッドを提供します)。public class TimePickerFragment : DialogFragment, TimePickerDialog.IOnTimeSetListener
TAG
はログのために初期化されます (MyTimePickerFragment は使用したい任意の文字列に変更できます)。timeSelectedHandler
アクションは、以下のように、null 参照例外を防ぐための空のデリゲートに初期化されます。public static readonly string TAG = "MyTimePickerFragment"; Action<DateTime> timeSelectedHandler = delegate { };
NewInstance
ファクトリ メソッドは、新しいTimePickerFragment
のインスタンスを作成するために呼び出されます。 このメソッドは、以下のように、TimePickerDialog
内でユーザーが [OK] ボタンをクリックしたときに呼び出されるAction<DateTime>
ハンドラーを受け取ります。public static TimePickerFragment NewInstance(Action<DateTime> onTimeSelected) { TimePickerFragment frag = new TimePickerFragment(); frag.timeSelectedHandler = onTimeSelected; return frag; }
フラグメントを表示する必要がある場合、Android は
DialogFragment
のメソッドである OnCreateDialog を呼び出します。 このメソッドは、新しいTimePickerDialog
オブジェクトを作成し、以下のように、それをアクティビティ、コールバック オブジェクト (TimePickerFragment
の現在のインスタンス)、および現在の時刻を使用して初期化します。public override Dialog OnCreateDialog (Bundle savedInstanceState) { DateTime currentTime = DateTime.Now; bool is24HourFormat = DateFormat.Is24HourFormat(Activity); TimePickerDialog dialog = new TimePickerDialog (Activity, this, currentTime.Hour, currentTime.Minute, is24HourFormat); return dialog; }
ユーザーが
TimePicker
ダイアログの時刻設定を変更すると、OnTimeSet
メソッドが呼び出されます。OnTimeSet
は、以下のように、現在の日付を使用してDateTime
オブジェクトを作成し、ユーザーによって選択された時刻 (時間と分) にマージします。public void OnTimeSet(TimePicker view, int hourOfDay, int minute) { DateTime currentTime = DateTime.Now; DateTime selectedTime = new DateTime(currentTime.Year, currentTime.Month, currentTime.Day, hourOfDay, minute, 0);
DateTime
オブジェクトは、作成時にTimePickerFragment
オブジェクトに登録されているtimeSelectedHandler
に渡されます。OnTimeSet
は、以下のように、このハンドラーを呼び出して、アクティビティの時刻表示を選択された時刻に更新します (このハンドラーは次のセクションで実装されます)。timeSelectedHandler (selectedTime);
TimePickerFragment の表示
DialogFragment
の実装が完了したので、以下のように NewInstance
ファクトリ メソッドを使用して DialogFragment
のインスタンスを作成し、DialogFragment.Show を呼び出すことでそれを表示します。
次のメソッドを MainActivity
に追加します。
void TimeSelectOnClick (object sender, EventArgs eventArgs)
{
TimePickerFragment frag = TimePickerFragment.NewInstance (
delegate (DateTime time)
{
timeDisplay.Text = time.ToShortTimeString();
});
frag.Show(FragmentManager, TimePickerFragment.TAG);
}
TimeSelectOnClick
は TimePickerFragment
のインスタンスを作成した後、アクティビティの時刻表示を渡された時刻値で更新する匿名メソッドのデリゲートを作成して渡します。 最後に、(DialogFragment.Show
を介して) TimePicker
ダイアログ フラグメントを起動して、TimePicker
をユーザーに表示します。
OnCreate
メソッドの最後に、次の行を追加して、ダイアログを起動する [PICK TIME] ボタンにイベント ハンドラーをアタッチします。
timeSelectButton.Click += TimeSelectOnClick;
[PICK TIME] ボタンがクリックされると、TimePicker
ダイアログ フラグメントをユーザーに表示するために TimeSelectOnClick
が呼び出されます。
手順を次に示します。
アプリをビルドし、実行します。 [PICK TIME] ボタンをクリックすると、以下のようにアクティビティの既定の時刻形式 (この場合は 12 時間制の AM/PM モード) で TimePickerDialog
が表示されます。
TimePicker
ダイアログで [OK] をクリックすると、以下のように、ハンドラーは選択された時刻でアクティビティの TextView
を更新した後に終了します。
次に、次のコード行を OnCreateDialog
の is24HourFormat
の宣言と初期化の直後に追加します。
is24HourFormat = true;
この変更により、TimePickerDialog
コンストラクターに渡されるフラグは強制的に true
になり、ホスティング アクティビティの時刻形式ではなく 24 時間制モードが使用されるようになります。 再度アプリをビルドして実行するときに、[PICK TIME] ボタンをクリックすると、以下のように、TimePicker
ダイアログが 24 時間制形式で表示されるようになります。
ハンドラーは DateTime.ToShortTimeString を呼び出して時刻をアクティビティの TextView
に出力するため、この時刻は引き続き既定の 12 時間制 AM/PM 形式で表示されます。
まとめ
この記事では、Android アクティビティからポップアップ モーダル ダイアログとして TimePicker
ウィジェットを表示する方法について説明しました。 サンプルの DialogFragment
の実装を提供し、IOnTimeSetListener
インターフェイスについて説明しました。 このサンプルでは、DialogFragment
がどのようにホスト アクティビティとやり取りして選択された時刻を表示するのかも示しました。