6

私の知る限り、Jelly Beans より前のバージョンでは、 TimePickerDialogSetを使用するときにとCancelボタンがありました。ジェリービーンズはボタンのみ。Done

ボタンをそのままにしてDone、ダイアログの外側をクリックしてダイアログを閉じることもできますが、ダイアログの外側onTimeSetListenerを押すと呼び出されDoneます。

それで、 DatePickerDialogの使用時にバグがあることを説明するこのスタックオーバーフローの質問を見つけました。DatePickerDialogを使用して問題を解決するには、初期化時に を に設定し、(Set) および(Cancel) onClick メソッドを処理する独自のボタンを実装する必要がありました。ボタンが呼び出されると、次のようにDatePicker値 にアクセスできるため、これは問題ありませんonDateSetListenernullBUTTON_POSITIVEBUTTON_NEGATIVESet

int yearPicked = dateDlg.getDatePicker().getYear();
int monthPicked = dateDlg.getDatePicker().getMonth();
int dayPicked = dateDlg.getDatePicker().getDayOfMonth();

したがって、 を使用する必要はありませんが、使用するonDateSetListener場合は、Set または Cancel を押したときに再度呼び出されます。

TimePickerDialogを同じ方法で使用しようとしましたが、問題は、BUTTON_POSITIVEonClick メソッド内で、以前のように時間と分の値にアクセスできないことです。これは、 TimePickerDialogがTimePickerを提供しないため、 DatePickerDialogがDatePickerを提供するためです。また、 を使用すると、何かを押すと呼び出されます。onTimeSetListener

Calendar cal = Calendar.getInstance();

int hour = cal.get(Calendar.HOUR_OF_DAY);
int min = cal.get(Calendar.MINUTE);

final TimePickerDialog timeDlg = new TimePickerDialog(PreferencesActivity.this, null, hour, min, true);

// Make the Set button
timeDlg.setButton(DialogInterface.BUTTON_POSITIVE, "Set", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int which) {
        if (which == DialogInterface.BUTTON_POSITIVE) {
            // CANNOT ACCES THE VALUES
            Toast.makeText(PreferencesActivity.this, "Set", Toast.LENGTH_SHORT).show();
        }
    }
});


// Set the Cancel button
timeDlg.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int which) {
        if (which == DialogInterface.BUTTON_NEGATIVE) {
            Toast.makeText(PreferencesActivity.this, "Cancel", Toast.LENGTH_SHORT).show();
        }
    }
});

timeDlg.show();
4

2 に答える 2

8

OnTimeSetListenerあなたのコメントに基づいて、「キャンセル」がクリックされた場合にロジックが実行されないように、コールバックをブール値で保護するのは簡単なはずです。

私はあなたのコードを簡単に試してみましたが、次のように問題なく動作するようでした:

private boolean mIgnoreTimeSet = false;

final TimePickerDialog timeDlg = new TimePickerDialog(PreferencesActivity.this, PreferencesActivity.this, hour, min, true);

// Make the Set button
timeDlg.setButton(DialogInterface.BUTTON_POSITIVE, "Set", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int which) {
        mIgnoreTimeSet = false;
        // only manually invoke OnTimeSetListener (through the dialog) on pre-ICS devices
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) timeDlg.onClick(dialog, which);
        Toast.makeText(getApplicationContext(), "Set", Toast.LENGTH_SHORT).show();
    }
});

// Set the Cancel button
timeDlg.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int which) {
        Toast.makeText(getApplicationContext(), "Cancel", Toast.LENGTH_SHORT).show();
        mIgnoreTimeSet = true;
        dialog.cancel();
    }
});

timeDlg.show();

@Override public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
    if (mIgnoreTimeSet) return;
    // get the values here - this will only run if 'Set' was clicked
}

例のために、あなたのPreferencesActivityimplementsを想定しましOnTimeSetListenerた。onTimeSet(...)は の後に呼び出されるためonClick(...)、ブール値を切り替えるだけで、コールバックの値を使用して何かを行うか、単に無視するかを決定できます。

理想的ではないことに同意する必要がありますが、少なくとも機能的です。休暇の後、「より良い」解決策をもう一度見てみます。

リフレクションを使用して内部で使用されるTimePickerウィジェットのハンドルを取得することも 1 つの方法ですが、これは将来の Android リリースで機能しなくなる可能性が高くなります。


// 編集: 潜在的な代替案? (未検証)

2 番目の選択肢。これは少し「クリーン」かもしれません: TimePickerDialog(空の) パブリック メソッドを拡張して上書きします。

public void onTimeChanged(TimePicker view, int hourOfDay, int minute)

そこで、ユーザーが設定した時間と分を追跡し、それらを返す 2 つのゲッターを実装します。次に、肯定的なボタンがクリックされた場合にのみ、ダイアログからこれらの値を取得しますが、「キャンセル」のためにフォールスルーします。基本的に、それ以降は不要になるOnTimeSetListenerため、呼び出されるかどうかは問題になりません。


// Edit2: ICS 以前のデバイスのサポート

提案されたソリューションがICS以前のデバイスで機能しないといういくつかのコメントを受け取った後、上記のコードに小さな変更を加えました.元の質問の範囲内ではありませんでした.

ICS 前と ICS 後のデバイスの主な違いは、ダイアログ ボタンのメソッドが実行OnTimeSetListenerされた後、コールバックが自動的に呼び出されないことです。onClick()そのための簡単な回避策はonClick()、ダイアログでメソッドを呼び出すことです。これにより、リスナーが呼び出されます。上記のソリューションでは、バージョン コード チェックを追加しました。そうしないと、リスナーが ICS 後のデバイスで 2 回呼び出され、望ましくない副作用が発生する可能性があるためです。

Android 2.1-update1 および Android 4.2.2 でテストおよび確認済みの動作。

于 2012-12-31T05:45:32.097 に答える
1

Nexus 7のJelly BeanのTimePickerDialogで同じ「Done-button-only」の問題が発生したときに、このスレッドを見つけました(私のNexus One、Gingerbreadには、同じTimePickerDialogの設定ボタンとキャンセルボタンがあります)。ただし、Nexus 7 (ビルド番号 JWR66Y) の 4.3 Jelly Bean へのその後の更新により、適切なボタン、[設定] と [キャンセル] が戻ってきたようです。

ただし、この問題を調査しているときに、このStackoverflow スレッドに出くわしました。このスレッドでは、DatePickerDialog のより大きな問題 (参照されているバグ レポートで TimePickerDialog についても同様の問題が示されています) の概要を綿密に説明し、解決策を提供しています。

Android の特定のバージョンでは正しく機能しないため、これらのダイアログの使用は慎重に検討する必要があることに注意してください (前述のスレッドで提供されているソリューションは、作成者によると「製品コードでは」使用されていません)。

于 2013-10-17T03:42:28.787 に答える