TimePickerDialogとは
そのまんま,時刻を設定するためのダイアログ.
画像はICS(Android 4.0.4のもの)
ICSではキャンセルボタンと設定ボタンが配置されている.
当然キャンセルボタンを押せば入力は無いし,設定を押せば入力が完了する(onTimeSet()が呼ばれる).
Jerry Beans以降(4.4.2 Kitkatまで確認)になると?
表示はこうなる.
キャンセルボタンが無くなり,設定ボタンは「完了」に変わっている.
不可解なのはここから.
- バックボタンで閉じても onTimeSet() が呼ばれて入力が完了する.
- ダイアログを枠外タップして消しても onTimeSet() が呼ばれて入力が完了する.
- 完了ボタンがクリックされると,なんと onTimeSet() が2回呼ばれる.
なんで?
意図した物かはわからない.意図したいこともよくわからない.
バグなのか?これ?
コード上は?
4.0.4のコードでは,こうなっている.
public void onClick(DialogInterface dialog, int which) {
if (mCallback != null) {
mTimePicker.clearFocus();
mCallback.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
mTimePicker.getCurrentMinute());
}
}
ボタンがクリックされるとコールバックのonTimeSetを呼び出す形だ.
ただ,コンストラクタの中でボタン設定をしており,完了ボタンではコールバックを設定し,キャンセルボタンではそもそもOnClickListenerをセットしていないため、 onClickは呼ばれない。
だから,当然完了ボタンをクリックしたときのみ onTimeSet が呼び出され,入力が完了する.
では Jerry Beans以降になると?
4.1.1のコードではこうなっている
public void onClick(DialogInterface dialog, int which) {
tryNotifyTimeSet();
}
public void updateTime(int hourOfDay, int minutOfHour) {
mTimePicker.setCurrentHour(hourOfDay);
mTimePicker.setCurrentMinute(minutOfHour);
}
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
/* do nothing */
}
private void tryNotifyTimeSet() {
if (mCallback != null) {
mTimePicker.clearFocus();
mCallback.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
mTimePicker.getCurrentMinute());
}
}
@Override
protected void onStop() {
tryNotifyTimeSet();
super.onStop();
}
Jerry Beans以降のコードになると,tryNotifyTimeSet() というメソッドが追加され,ここでコールバックのonTimeSet()を呼び出しているのがわかる.
ただ,このメソッドが onClick と,onStopで呼び出されている.
だから,TimePickerDialogを閉じると, onStop() から tryNotifyTimeSet() が呼ばれて入力が完了されてしまう.
完了ボタンをクリックすると, onClick() で tryNotifyTimeSet() が呼び出されてから,さらにダイアログが閉じたタイミングの onStop() からも tryNotifyTimeSet() が呼ばれてしまう.
もちろん,端末をスリープしただけでも onTimeSet() が呼ばれる.
入力のキャンセルができなくなっている.
どうしてこうなった
どう対応した物か…