こんな感じのダイアログで30分単位の時刻を選択するやつを作ったので書いておく。
- Fragmentから呼び出して使う(DialogFragmentベース)
- Gingerbread(API Level 10)でも使える
- 選択した時と分をintで取得
- 初期値をCalenderか、intの時と分で指定できる
- v11以上ではNumberPickerを使う
- v10以下ではSpinnerを使う
使い方
ダイアログを開くときはこんな感じで呼び出す。
初期値はCalendarで渡すか、 set(int hour, int minute)で渡す。
TimePickerFragment picker = TimePickerFragment.newInstance(this);
picker.set(calendar);
picker.show(getFragmentManager(), "time_picker");
選択された値は、呼び出し元FragmentのonTimeSetで受け取る。
HogeFragment
public class HogeFragment extends Fragment implements TimePickerFragment.TimePickerListener {
@Override
public void onTimeSet(int hourOfDay, int minute) {
// 選択された時、分がhourOfDay、minuteに入ってくる
}
}
本体コード
DialogFragmentの全体はこんな感じ。
TimePickerFragment.java
public class TimePickerFragment extends DialogFragment {
public interface TimePickerListener {
void onTimeSet(int hourOfDay, int minute);
}
public static TimePickerFragment newInstance(Fragment fragment) {
TimePickerFragment dialog = new TimePickerFragment();
dialog.setTargetFragment(fragment, 0);
return dialog;
}
private TimePickerListener getListener() {
try {
return (TimePickerListener) getTargetFragment();
} catch (ClassCastException e) {
return null;
}
}
private View hour;
private View minute;
public void set(int hour, int minute) {
Bundle args = getArguments();
if (args == null) {
args = new Bundle();
}
args.putInt("hour", hour);
args.putInt("minute", minute);
setArguments(args);
}
public void set(Calendar calendar) {
this.set(calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE));
}
private View createPickerView() {
View view = LayoutInflater.from(getActivity()).inflate(R.layout.time_picker, null);
int hourValue;
int minuteValue;
Bundle args = getArguments();
if (args != null && args.containsKey("hour")) {
hourValue = args.getInt("hour");
minuteValue = args.getInt("minute");
} else {
// 初期値が指定されなかった場合は現在時刻
Calendar now = Calendar.getInstance();
hourValue = now.get(Calendar.HOUR_OF_DAY);
minuteValue = now.get(Calendar.MINUTE);
}
// 30分刻みに繰り上げる
if (minuteValue == 0) {
minuteValue = 0;
} else if (minuteValue <= 30) {
minuteValue = 30;
} else {
minuteValue = 0;
hourValue = (hourValue + 1 > 23 ? 0 : hourValue + 1);
}
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD_MR1) {
NumberPicker hour = (NumberPicker) view.findViewById(R.id.picker_hour);
hour.setMinValue(0);
hour.setMaxValue(23);
hour.setValue(hourValue);
this.hour = hour;
NumberPicker minute = (NumberPicker) view.findViewById(R.id.picker_minute);
minute.setMinValue(0);
minute.setMaxValue(5);
minute.setDisplayedValues(new String[]{"00", "30", "00", "30", "00", "30"});
minute.setValue(minuteValue > 29 ? 1 : 0);
this.minute = minute;
} else {
Spinner hour = (Spinner) view.findViewById(R.id.picker_hour);
hour.setSelection(hourValue);
this.hour = hour;
Spinner minute = (Spinner) view.findViewById(R.id.picker_minute);
minute.setSelection(minuteValue > 29 ? 1 : 0);
this.minute = minute;
}
return view;
}
private int getHour() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD_MR1) {
NumberPicker picker = (NumberPicker) hour;
return picker.getValue();
} else {
Spinner spinner = (Spinner) hour;
return Integer.parseInt((String) spinner.getSelectedItem());
}
}
private int getMinute() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD_MR1) {
NumberPicker picker = (NumberPicker) minute;
return (picker.getValue() % 2) == 1 ? 30 : 0;
} else {
Spinner spinner = (Spinner) minute;
return Integer.parseInt((String) spinner.getSelectedItem());
}
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
super.onCreateDialog(savedInstanceState);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(createPickerView());
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
TimePickerListener listener = getListener();
if (listener != null) {
listener.onTimeSet(getHour(), getMinute());
}
}
});
builder.setNegativeButton(android.R.string.cancel, null);
builder.setCancelable(true);
return builder.create();
}
}
ポイントとしては、"00"と"30"の2値だけだと、クルクル~ってスクロールしないので、00と30を数回繰り返した値にしてる。
minute.setDisplayedValues(new String[]{"00", "30", "00", "30", "00", "30"});
Layoutファイルはv11以上向けのNumberPicker版とv10以下向けのSpinner版を用意
layout-v11/time_picker.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
<NumberPicker
android:id="@+id/picker_hour"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:text=":"
android:textSize="24sp" />
<NumberPicker
android:id="@+id/picker_minute"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</FrameLayout>
layout/time_picker.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal"
android:padding="16dp">
<Spinner
android:id="@+id/picker_hour"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@array/picker_item_hour"
android:gravity="center_vertical|right" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:gravity="center"
android:text=":"
android:textColor="#ffffff"
android:textSize="24sp" />
<Spinner
android:id="@+id/picker_minute"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@array/picker_item_minute"
android:gravity="center_vertical|left" />
</LinearLayout>
</FrameLayout>
values/picker_item.xml
<resources>
<string-array name="picker_item_hour">
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>6</item>
<item>7</item>
<item>8</item>
<item>9</item>
<item>10</item>
<item>11</item>
<item>12</item>
<item>13</item>
<item>14</item>
<item>15</item>
<item>16</item>
<item>17</item>
<item>18</item>
<item>19</item>
<item>20</item>
<item>21</item>
<item>22</item>
<item>23</item>
</string-array>
<string-array name="picker_item_minute">
<item>00</item>
<item>30</item>
</string-array>
</resources>