LoginSignup
7
7

More than 5 years have passed since last update.

Android 4.1(Jerry Beans)以降のTimePickerDialogの動作が不可解

Last updated at Posted at 2014-08-22

TimePickerDialogとは

そのまんま,時刻を設定するためのダイアログ.
画像はICS(Android 4.0.4のもの)

01.png

ICSではキャンセルボタンと設定ボタンが配置されている.
当然キャンセルボタンを押せば入力は無いし,設定を押せば入力が完了する(onTimeSet()が呼ばれる).

Jerry Beans以降(4.4.2 Kitkatまで確認)になると?

表示はこうなる.

02.png

キャンセルボタンが無くなり,設定ボタンは「完了」に変わっている.
不可解なのはここから.

  • バックボタンで閉じても onTimeSet() が呼ばれて入力が完了する.
  • ダイアログを枠外タップして消しても onTimeSet() が呼ばれて入力が完了する.
  • 完了ボタンがクリックされると,なんと onTimeSet() が2回呼ばれる.

なんで?

意図した物かはわからない.意図したいこともよくわからない.
バグなのか?これ?

コード上は?

4.0.4のコードでは,こうなっている.

TimePickerDialog.java
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のコードではこうなっている

TimePickerDialog.java
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() が呼ばれる.
入力のキャンセルができなくなっている.

どうしてこうなった

どう対応した物か…

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7