AndroidのTimePickerDialogに苦しめられた話

  • 2
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

だいたいこれ。
http://qiita.com/tetsukay/items/a28a572775bc3648e78b

時間を選択する際に、OK/キャンセル以外の第三の選択肢「未定」を追加したいってことがありました。
Android 5.0で見る限りは、setButtonに BUTTON_NEUTRAL でボタンを追加することで簡単に出来ましたが、4.4などのいくつかの端末で問題が発生しました。

問題1:キャンセルしたくても出来ない

書いてあるように、 onStop で最終的にコンストラクタで設定したlistenerが呼ばれる。
setButton とかでボタンを追加しても、消えるときに onStop が呼ばれてしまうので、
追加したボタンのアクション -> コンストラクタのlistener
が自動的に呼び出される。

問題2:コンストラクタのlistenerを使わないと、設定された時刻を取れない

似たようなクラスである、 DatePickerDialog には getDatePicker というgetterが存在しており、問題1と同様のバグはあるものの、
コンストラクタではnullを渡す -> setButtonでPOSITIVEなボタンを再定義
で逃げれた。
ただ、TimePickerDialog ではTimePickerを取り出せないので、その回避策が取れない。
(無理したら、idとかから取れるのかもしれないけど、内部状況に依存するので微妙)

結論

TimePickerDialog 使えねぇ

とりあえずな回避策

styles.xmlには下記がある前提で、

    <style name="AppTheme.Picker" parent="AppTheme">
        <item name="android:textColorPrimary">@color/text_gray</item>
    </style>

AlertDialog.Builder を使って、自作しました。

    public static Dialog showTimePickerDialog(Context context,
                                              Calendar defaultValue,
                                              final TimePickerDialog.OnTimeSetListener listener,
                                              DialogInterface.OnClickListener pendingListener) {
        Calendar target = defaultValue == null ? Calendar.getInstance() : defaultValue;
        int hour = target.get(Calendar.HOUR_OF_DAY);
        int minute = target.get(Calendar.MINUTE);

        final TimePicker picker = new TimePicker(new ContextThemeWrapper(context, R.style.AppTheme_Picker));
        picker.setIs24HourView(true);
        picker.setCurrentHour(hour);
        picker.setCurrentMinute(minute);

        AlertDialog dialog = new AlertDialog.Builder(context)
                .setView(picker)
                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        listener.onTimeSet(picker, picker.getCurrentHour(), picker.getCurrentMinute());
                    }
                })
                .setNegativeButton(android.R.string.cancel, null)
                .create();


        if (pendingListener != null) {
            String pendingLabel = dialog.getContext().getString(R.string.dialog_button_pending);
            dialog.setButton(DialogInterface.BUTTON_NEUTRAL, pendingLabel, pendingListener);
        }
        dialog.setCancelable(false);
        dialog.show();

        return dialog;
    }

TimePickerDialogをSupport Libraryに入れてほしい。。
302SHでは、5.0と同様に問題が無かった。何故。。