2012-12-30 7 views
6

Soweit mir bekannt ist, Versionen vor Jelly Beans, hatte Set und Tasten Abbrechen, wenn TimePickerDialog verwenden. Jelly Beans hat nur Fertig Knopf.Gibt es eine Möglichkeit, Abbrechen in Android JellyBean TimePickerDialog zu verwenden?

konnte ich nur verlassen die Taste Fertig, und könnte den Dialog schließen, indem außerhalb des Dialogs klicken, aber meine onTimeSetListener aufgerufen wird, wenn oder außerhalb des Dialogs Fertig drücken.

So fand ich this stackoverflow question, die beschreibt, dass es einen Fehler bei der Verwendung DatePickerDialog gibt. Um das Problem mit DatePickerDialog zu beheben, musste ich beim Initialisieren die onDateSetListener auf null setzen und meine eigenen Schaltflächen implementieren, um die BUTTON_POSITIVE (Set) und BUTTON_NEGATIVE (Abbrechen) OnClick-Methode zu behandeln. Welches ist in Ordnung, denn wenn die Taste Set genannt Ich mag die Datepicker Werte zugreifen können diese

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

So gibt es keine Notwendigkeit onDateSetListener zu verwenden, aber wenn ich würde, würde es wieder aufgerufen werden, wenn Sie die Taste Setzen oder Abbrechen.

Ich versuchte TimePickerDialog die gleiche Art und Weise, aber das Problem ist, dass innerhalb BUTTON_POSITIVE onClick-Methode zu verwenden, ich nicht die Stunde und Minuten Werte wie vor zugreifen können, weil TimePickerDialog nicht Timepicker als DatePickerDialog bieten hat bietet DatePicker. Und wenn ich wieder onTimeSetListener verwenden würde, würde es durch Drücken von irgendetwas aufgerufen werden.

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(); 
+0

Nun, Sie können immer noch eine 'TimePickerDialog.OnTimeSetListener' registrieren, um die eingegebenen Werte zu erfassen, aber tun Sie nichts damit, wenn die negative Schaltfläche angetippt wird, oder? –

+0

Das ist das Problem, OnTimeSetListener wird aufgerufen, wenn Positiv, Negativ und Zurück-Taste gedrückt wird. – Marko

+1

Ich hatte das gleiche Problem, beachten Sie, dass die unten akzeptierte Antwort nicht abwärtskompatibel ist (pre jb). Sice Ich brauchte SDK 8+, löste es mit einem Boolean innerhalb eines erweiterten Fragmentdialogs und überwand onClick() dort. – auval

Antwort

8

Basierend auf Ihrem Kommentar, es sollte einfach genug sein, um den OnTimeSetListener Rückruf mit einem boolean zu schützen Ihre Logik zu verhindern, im Fall von Laufe ‚Abbrechen‘ geklickt wird.

ich ein schnelles Spiel mit Ihrem Code hatte, und die folgende schien in Ordnung zu arbeiten:

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 
} 

Aus Gründen des Beispiels habe ich Ihre PreferencesActivity Geräte OnTimeSetListener angenommen. Da onTimeSet(...) nach onClick(...) aufgerufen wird, können Sie einfach einen booleschen Wert umschalten, der bestimmt, ob Sie etwas mit den Werten im Callback machen oder sie einfach ignorieren sollten.

Ich muss zustimmen, es ist nicht ideal, aber zumindest funktional. Nach den Ferien werde ich versuchen, noch einmal nach einer "besseren" Lösung zu suchen.

Eine Alternative wäre, Reflektion zu verwenden, um das intern verwendete TimePicker Widget zu handhaben, aber das wird in zukünftigen Android-Versionen eher brechen.


// Bearbeiten: Mögliche Alternative?(Nicht getestet)

Zweite Alternative, die ein bisschen ‚sauberen‘ sein könnten: verlängern TimePickerDialog und überschreiben die (leer) öffentliche Methode:

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

Dort, verfolgen die vom Benutzer eingestellten Stunde des Tages und der Minute und implementieren zwei Getter, die sie zurückgeben. Dann holen Sie sich diese Werte nur dann aus dem Dialog, wenn Sie auf die positive Schaltfläche klicken, sondern nur auf "Abbrechen". Im Grunde brauchen Sie dann keine OnTimeSetListener mehr, und daher ist es egal, ob es jemals aufgerufen wird oder nicht.


// Edit2: Unterstützung für Pre-ICS-Geräte

Nach ein paar Bemerkungen über die vorgeschlagene Lösung nicht funktioniert auf Pre-ICS-Geräten empfangen, habe ich zu dem obigen Code eine kleine Änderung - Auch wenn es nicht im Rahmen der ursprünglichen Frage war.

Der Hauptunterschied zwischen Pre-ICS- und Post-ICS-Geräten besteht darin, dass der Callback nicht automatisch aufgerufen wird, nachdem die onClick()-Methode (n) der Dialogschaltfläche ausgeführt wurde. Eine einfache Abhilfe hierfür besteht darin, die Methode onClick() für den Dialog aufzurufen, der dann den Listener aufruft. In der obigen Lösung habe ich einen Versionscode-Check hinzugefügt, weil sonst Ihr Listener bei Post-ICS-Geräten zweimal aufgerufen wird, was zu unerwünschten Nebenwirkungen führen kann.

Getestet und bestätigt Verhalten auf Android 2.1-Update1 und Android 4.2.2.

+0

Vielen Dank für Ihre Antwort, verbringen Sie einen Tag mit dem Code spielen und suchen. Der Trick mit Boolean funktioniert gut. Meine PreferencesActivity implementiert OnTimeListener nicht, aber ich habe die Idee. – Marko

+0

Dies funktioniert mit 4.1, funktioniert aber nicht mit 2.2 –

+1

@AdilMalik: nachdem ich einige der Kommentare gelesen habe, die besagen, dass die vorgeschlagene Lösung nicht auf Pre-ICS-Geräten funktioniert, habe ich eine kleine Änderung vorgenommen, um dies zu berücksichtigen. Weitere Informationen finden Sie in der 2. Bearbeitung. –

1

Ich fand diesen Thread, wenn das gleiche "Done-button-only" -Problem mit dem TimePickerDialog für Jelly Bean auf meinem Nexus 7 (mein Nexus One, Gingerbread, mit Set und Cancel-Tasten für den gleichen TimePickerDialog). Es scheint jedoch, dass mit einem anschließenden Update auf 4.3 Jelly Bean auf meinem Nexus 7 (Build Nummer JWR66Y), die richtigen Tasten, Set und Abbrechen, zurückgekehrt sind.

Bei der Untersuchung dieses Problems stieß ich jedoch auf diese Stackoverflow thread, die eher größere Probleme mit DatePickerDialog skizziert (mit ähnlichen Problemen für TimePickerDialog in einem referenzierten Fehlerbericht angegeben) und bietet eine Lösung.

Achten Sie darauf, dass die Verwendung dieser Dialoge sorgfältig betrachtet werden muss, da sie in bestimmten Versionen von Android nicht richtig funktionieren (die im oben genannten Thread angebotene Lösung wird laut Autor nicht "in Produktionscode" verwendet).

+0

Schön zu hören, dass das Problem mit der neuesten Version behoben wurde. Vielen Dank – Marko

Verwandte Themen