Jelly Bean DatePickerDialog - Gibt es eine Möglichkeit, abzubrechen?
--- Hinweis an die Moderatoren: Heute (15. Juli), habe ich bemerkt, dass jemand bereits konfrontiert dieses problem hier. Aber ich bin mir nicht sicher, ob es angemessen ist, um diese zu schließen als Duplikat, da ich denke, dass ich eine viel bessere Erklärung für das Problem. Ich bin mir nicht sicher, ob ich es Bearbeiten sollte, die andere Frage und fügen Sie diesen Inhalt gibt es, aber ich bin wohl nicht ändern, jemand anderes die Frage zu viel. ---
Habe ich etwas komisch hier.
Glaube ich nicht, das problem hängt davon ab, welches SDK Sie bauen vor. Das Gerät, OS-version ist es, was zählt.
Problem #1: Inkonsistenz standardmäßig
DatePickerDialog
wurde geändert (?) in Jelly Bean und jetzt stellt nur eine Getan - Taste. Frühere Versionen enthalten einen Abbrechen - Taste, und dies kann Einfluss auf user experience (Inkonsistenz, Muskel-Speicher von vorherigen Android-Versionen).
Replizieren: Erstellen Sie ein basic-Projekt. Setzen Sie diese in onCreate
:
DatePickerDialog picker = new DatePickerDialog(
this,
new OnDateSetListener() {
@Override
public void onDateSet(DatePicker v, int y, int m, int d) {
Log.d("Picker", "Set!");
}
},
2012, 6, 15);
picker.show();
Erwartet: Eine Abbrechen - Taste erscheinen im dialog.
Strom: Eine Abbrechen Schaltfläche nicht angezeigt.
Screenshots: 4.0.3 (OK) und 4.1.1 (möglicherweise falsch?).
Problem #2: falsch abtun Verhalten
Dialog aufruft, je nachdem, welcher Hörer sollte es in der Tat, und dann immer Anrufe OnDateSetListener
Zuhörer. Cancelling-noch immer ruft die set-Methode, und es ruft die Methode zweimal.
Replizieren: #1 code, sondern fügen Sie folgenden code ein (Sie sehen dies löst die #1, aber nur optisch/UI):
picker.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d("Picker", "Cancel!");
}
});
Erwartet:
- Drücken der ZURÜCK-Taste oder klicken außerhalb der dialog sollte nichts tun.
- Drücken von "Abbrechen" drucken Picker Abbrechen!.
- Drücken der Taste "Set" drucken Picker Set!.
Strom:
- Drücken der ZURÜCK-Taste oder einen Klick außerhalb des dialog-prints Picker Set!.
- Drücken von "Abbrechen" druckt Picker Abbrechen! und dann Picker Set!.
- Drücken der Taste "Set" druckt Picker Set! und dann Picker Set!.
Log Linien zeigen das Verhalten:
07-15 12:00:13.415: D/Picker(21000): Set!
07-15 12:00:24.860: D/Picker(21000): Cancel!
07-15 12:00:24.876: D/Picker(21000): Set!
07-15 12:00:33.696: D/Picker(21000): Set!
07-15 12:00:33.719: D/Picker(21000): Set!
Sonstige Erläuterungen und Kommentare
- Wickeln Sie es um eine
DatePickerFragment
egal. Ich vereinfachte das problem für Sie, aber ich habe es getestet.
InformationsquelleAutor der Frage davidcesarino | 2012-07-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hinweis: Feste wie der LutscherQuelle hier. Automatisierte Klasse für den Einsatz in clients (kompatibel mit allen Android-Versionen) aktualisiert.
TL;DR: 1-2-3 Toten einfache Schritte für eine Globale Lösung:
OnDateSetListener
in Ihrer Aktivität (oder ändern Sie die Klasse, um Ihre Bedürfnisse anzupassen).Trigger-Dialogfeld mit diesem code (in diesem Beispiel, benutze ich es in einem
Fragment
):Und das ist alles was es braucht! Der Grund, warum ich immer noch meine Antwort als "akzeptiert" ist, weil ich immer noch lieber meine Lösung, da es eine sehr kleine Stellfläche im client-code, befasst sich mit dem grundlegenden Problem (der listener aufgerufen wird, in der framework-Klasse), funktioniert über config-änderungen und-Routen der code-Logik, um die default-Implementierung in den vorherigen Android-Versionen nicht geplagt von diesem Fehler (siehe Klasse Quelle).
Ursprüngliche Antwort (behalten aus historischen und didaktischen Gründen):
Fehler Quelle
OK, sieht aus wie es ist in der Tat ein bug und schon jemand anderes gefüllt. Problem 34833.
Habe ich gefunden, dass das problem möglicherweise in
DatePickerDialog.java
. Wo es heißt:Ich denke, es hätte sein können:
Nun, wenn jemand kann mir sagen, wie kann ich vorschlagen, einen patch/bug-report zu Android, ich würde mich freuen. Mittlerweile habe ich vorgeschlagen, eine mögliche Lösung (einfach) als angehängte version von
DatePickerDialog.java
in der Ausgabe.Konzept zu vermeiden, die Fehler
Legen Sie den Hörer auf
null
im Konstruktor, und erstellen Sie Ihre eigenenBUTTON_POSITIVE
Schaltfläche später. Das ist es, details siehe unten.Das problem tritt auf, weil
DatePickerDialog.java
wie Sie sehen können, in der Quelle fordert eine Globale variable (mCallBack
) , speichert der listener, die übergeben wurde, im Konstruktor:So, der trick ist, um eine
null
listener gespeichert werden, wie der Hörer, und dann Rollen Sie Ihre eigenen Satz von Tasten (unten ist der original code aus #1, aktualisiert):Ist es jetzt funktionieren wird, da die Möglichkeit der Korrektur, die ich oben geschrieben.
Und da
DatePickerDialog.java
prüft, ob einnull
Wann immer es liestmCallback
(seit den Tagen des API 3/1.5 es scheint --- kann nicht überprüfen, Honeycomb natürlich), es wird nicht die Ausnahme auslöst. Angesichts Lollipop das Problem behoben wurde, werde ich nicht zu schauen es: nutzen Sie einfach die default-Implementierung (in der Klasse, die ich zur Verfügung gestellt).Zuerst hatte ich Angst, nicht den Aufruf der
clearFocus()
aber ich habe hier getestet und die Log-Linien waren sauber. So, die Zeile habe ich vorgeschlagen, vielleicht sogar nicht notwendig, nachdem alle, aber ich weiß es nicht.Kompatibilität mit früheren API-Ebenen (bearbeitet)
Als ich, wies in den Kommentar unten, das war ein Konzept, und Sie können laden Sie die Klasse ich bin mit meinem Google Drive-Konto. Die Art, wie ich verwendet, die Standard-system-Implementierung verwendet wird, auf Versionen nicht betroffen von dem bug.
Nahm ich ein paar Annahmen (die Namen von Schaltflächen, etc.) geeignet sind für meine Bedürfnisse, weil ich wollte, zu verringern, boilerplate code in der client-Klassen auf ein minimum. Volle Nutzung Beispiel:
InformationsquelleAutor der Antwort
Ich werde mein eigenes riff auf die Lösung David Cesarino gepostet, falls Sie sich nicht mit Fragmenten, und wollen eine einfache Möglichkeit, es zu beheben, die in allen Versionen (2.1 thru 4.1):
InformationsquelleAutor der Antwort dmon
Bis der Fehler behoben wird schlage ich vor, Sie nicht zu verwenden, DatePickerDialog oder TimePickerDialog. Verwenden Sie benutzerdefinierte gemacht AlertDialog mit TimePicker/DatePicker-widget;
Ändern TimePickerDialog mit;
Ändern DatePickerDialog mit;
InformationsquelleAutor der Antwort cirit
Den man für TimePicker basiert auf der Lösung von David Cesarino , "TL;DR: 1-2-3 Toten einfache Schritte für eine Globale Lösung"
TimePickerDialog nicht die Funktionalität wie DatePickerDialog.getDatePicker.
So, OnTimeSetListener Hörer zur Verfügung gestellt werden.
Nur, um die ähnlichkeit mit DatePicker workaround-Lösung habe ich beibehalten, die alten mListener Konzept. Sie können es ändern, wenn Sie benötigen.
Aufrufen und Zuhörer ist die gleiche wie die ursprüngliche Lösung.
Nur sind
erweitern übergeordneten Klasse,
Implementieren
Beispiel Aufruf
(Aktualisierung Griff Abbrechen)
InformationsquelleAutor der Antwort Tejasvi Hegde
In den Fall, jemand will eine schnelle Abhilfe, hier ist der code, den ich verwendet:
}
Wo layout.date_picker_view ist ein einfaches layout-Ressource mit einem DatePicker, da es nur ein element:
Hier ist die vollständige tutorial in Fall, dass Sie interessiert sind.
InformationsquelleAutor der Antwort daniel_c05
Meine einfache Lösung. Wenn Sie möchten, um es brennen wieder einfach laufen "resetFired" (sagen, beim öffnen des dialogs wieder).
InformationsquelleAutor der Antwort Daniel Ryan
Die Art und Weise habe ich es geschafft diese situation wurde mit einem flag und überschreiben der onCancel und onDismiss Methoden.
onCancel wird nur aufgerufen, wenn der Benutzer berührt außerhalb des Dialogfensters oder die zurück-Taste.
onDismiss immer aufgerufen wird,
Einstellung eine fahne in die onCancel-Methode kann helfen, die filter in der onDismiss Methode die Absicht des Benutzers: Abbruch der Aktion oder Aktion durchgeführt. Nachfolgend einige code, der zeigt die Idee.
InformationsquelleAutor der Antwort Alvaro
Nach Ankur Chaudhary ist genial Antwort auf die ähnliche
TimePickerDialog
Problem, wenn wir überprüft, innerhalbonDateSet
wenn die AnsichtisShown()
oder nicht, es löst das ganze Problem mit minimalem Aufwand, ohne die Notwendigkeit für die Erweiterung der Farbauswahl oder bei der überprüfung auf einige abscheuliche flags gehen, um den code, oder sogar die Prüfung für die OS-version, nur Folgendes tun:und natürlich die gleiche getan werden kann, für
onTimeSet
als pro Ankur AntwortInformationsquelleAutor der Antwort AbdelHady
Gibt es eine sehr einfache Lösung, wenn Ihre Anwendung nicht mit der Aktion bar. Beachten Sie übrigens, dass einige Anwendungen verlassen sich auf diese Funktionalität zu arbeiten, weil die Aufhebung der date picker hat eine Besondere Bedeutung (z.B. löscht er das date-Feld mit einer leeren Zeichenfolge, die für manche apps ist eine gültige und sinnvolle Art der Eingabe) und die Verwendung von boolean-flags zu verhindern, dass das Datum festgelegt wird zweimal auf OK, wird dir nicht helfen in diesem Fall.
Re. die eigentliche Korrektur, Sie haben keinen um erstellen Sie neue Schaltflächen oder Ihren eigenen dialog. Der Punkt ist, um kompatibel zu sein mit den beiden, die ältere Versionen von Android, die buggy sind (4.) und jede Zukunft, wenn die letztere ist unmöglich, sicher, natürlich.
Beachten Sie, dass in Android 2., der onStop() für android.app.Dialog tut überhaupt nichts, und in der 4.* es tut mActionBar.setShowHideAnimationEnabled(false) ist nur wichtig, wenn Ihre app über eine action bar. Der onStop() in DatePickerDialog, die erbt von Dialog, trägt nur mDatePicker.clearFocus() (wie Sie das neueste Update für Android Quellen 4.3), die nicht wichtig erscheinen.
Ersetzt also onStop (), eine Methode, die nichts tut, sollte in vielen Fällen beheben Sie Ihre app und sicherzustellen, dass es so bleiben für die absehbare Zukunft. So erweitern Sie ganz einfach DatePickerDialog Klasse mit Ihren eigenen und überschreiben onStop() mit einer dummy-Methode. Sie müssen auch ein oder zwei Konstruktoren, wie pro Ihre Anforderungen.
Beachten Sie auch, dass man nicht versucht sein, zu übertreiben, diese zu beheben, indem Sie z.B. versuchen, etwas zu tun mit der Tätigkeit bar direkt, als würde beschränken Sie Ihre Kompatibilität zu den neuesten Versionen von Android nur. Beachten Sie auch, dass es schön wäre, um der Lage sein, die super für den DatePicker-der onStop (), da der Fehler nur in der onStop() in DatePickerDialog selbst, aber nicht in DatePickerDialog ist super Klasse. Dies würde jedoch erfordern, die Sie anrufen, super.super.onStop() aus der custom-Klasse, die Java-lassen Sie nicht zu tun, da geht es gegen die Verkapselung Philosophie 🙂
Unten ist meine kleine Klasse, die ich verwendet, um verride DatePickerDialog.
Ich hoffe, dieser Kommentar wäre nützlich für jemanden.
Wojtek Jarosz
}
InformationsquelleAutor der Antwort Wojtek Jarosz
Versuchen Sie die unten-Konzepte.
die onDateSet () - Methode ruft zweimal (wenn u sind bei der Prüfung emulator.er ruft zweimal.Wenn real Gerät ruft dann richtig single Zeit.Wenn Sie mit einem emulator verwenden Sie dann den Zähler.wenn Sie in einem echten Gerät dann ignorieren counter-variable.Für echtes Gerät sein, für mich zu arbeiten.)
wenn der Benutzer auf die Schaltfläche klickt in DatePickerDialog .
für diese sollten Sie pflegen einen Zähler Wert und nichts tun, wenn die mothod fordert erste mal und führen Sie die operation, wenn die Methode aufruft 2. mal.
Siehe unten coding snippets
Für die Stornierung des datepicker dilalog seine Arbeit für mich.Für emulator-sein nicht wokring
Seine Arbeit für mich für ein richtiges Gerät.Aber für emulator-es funktioniert nicht richtig.Ich denke, die ein android-emulator Fehler.
InformationsquelleAutor der Antwort SIVAKUMAR.J
Eine einfache Lösung wäre die Verwendung einer booleschen überspringen zweiten Lauf
InformationsquelleAutor der Antwort chamikaw
Können Sie überschreiben onCancel() und setOnDismissListener() zum erkennen von negativen user-Aktionen. Und mit einem DatePickerDialog.BUTTON_POSITIVE Sie wissen, dass der Benutzer möchte einen neuen Termin.
dann überprüfen Sie für setDate:
InformationsquelleAutor der Antwort Markus Rubey
Hier ist mein workaround Klasse für DatePickerDialog auf "Abbrechen" button verwerfen, indem Sie zurück-Taste. Copy&verwenden, in der Art von DatePickerDialog (Weil der Hörer ist stateful, müssen wir neue Instanz, wenn verwenden, ansonsten mehr code erforderlich ist, zu machen es funktioniert)
Verwenden:
Klasse:
}
InformationsquelleAutor der Antwort The Sea
Ich bin mit date Picker, time Picker und Anzahl Kommissionierer. Die Anzahl Kommissionierer rufen Sie onValueChanged, wenn der Benutzer wählt eine Nummer, vor der picker ist entlassen, also ich hatte bereits eine Struktur wie diese, etwas zu tun mit dem Wert nur, wenn der picker ist entlassen:
Ich erweiterte Sie diese Option, um benutzerdefinierte onClickListeners für meine buttons, mit einem argument zu sehen, auf welche Schaltfläche geklickt wurde. Jetzt kann ich prüfen, welcher button wurde angezapft, bevor ich meine endgültige Wert:
Dann erweiterte ich, dass die Arbeit mit den Datums-und Zeit-Typen für Datums-und uhrzeitauswahl sowie den Typ int für die Anzahl Pflücker.
Ich dies geschrieben, weil ich dachte, es war einfacher, als einige der oben genannten Lösungen, aber jetzt, dass ich ' ve enthalten den code, ich denke, es ist nicht viel einfacher! Aber es passte sehr gut in die Struktur, die ich bereits hatte.
Update für Lollipop: Anscheinend ist dieser bug passiert nicht auf allen Android-4.1-4.4 Geräte, da erhielt ich ein paar Berichte von Benutzern, deren Datums-und uhrzeitauswahl nicht aufrufen onDateSet und onTimeSet Rückrufe. Und der bug offiziell behoben, die in Android 5.0. Mein Ansatz funktioniert nur auf Geräten, bei denen der Fehler anwesend ist, weil meine benutzerdefinierte Schaltflächen nicht rufen Sie das Dialogfeld onClick-handler ist der einzige Ort, dass onDateSet und onTimeSet aufgerufen, wenn der bug nicht vorhanden ist. Ich aktualisierte mein code oben, um rufen Sie das Dialogfeld onClick, so dass es jetzt funktioniert oder nicht, ob der bug vorhanden ist.
InformationsquelleAutor der Antwort arlomedia
Ich mochte David Cesarino ' s Antwort oben, aber wollte etwas, das war ein drop-in-Ersatz für den gebrochenen dialog und arbeiten würde, auf jeder dialog, vielleicht fehlt kündigen /falsche Abbrechen Verhalten. Hier sind abgeleitete Klassen für DatePickerDialog /TimePickerDialog funktionieren sollte, das als drop-in Ersatz. Diese sind nicht benutzerdefinierte Ansichten. Es verwendet die system-dialog, sondern ändert nur den Abbrechen - /zurück-button Verhalten wie erwartet funktioniert.
Diese Arbeit sollte auf API-Ebene 3 und höher. Also, im Grunde jede Android-version (getestet habe ich es auf jellybean und lollipop speziell).
DatePickerDialog:
TimePickerDialog:
InformationsquelleAutor der Antwort stuckj
Meine funktionierende version mit ClearButton Verwendung von Lambda-Ausdrücken:
InformationsquelleAutor der Antwort Vasiliy Prokopishin
Für TimePickerDialog die Abhilfe kann wie folgt sein:
Ich delegieren alle Ereignisse wrapper KitKatSetTimeListener, und nur Feuer, zurück zum ursprünglichen OnTimeSetListener im Falle BUTTON_POSITIVE geklickt wird.
InformationsquelleAutor der Antwort southerton
Nach der Prüfung einige der Anregungen hier gepostet, ich persönlich denke, diese Lösung ist die einfachste.
Ich übergeben Sie "null" als meine Zuhörer in der DatePickerDialog Konstruktor, und dann wenn ich auf die Schaltfläche "OK" ich rufe meine onDateSearchSetListener:
InformationsquelleAutor der Antwort Birk Bonnicksen
Ich weiß, dieser Beitrag ist hier schon seit fast einem Jahr, aber ich dachte, ich sollte post meine Erkenntnisse.
Sie konnte noch immer die Zuhörer(anstatt es zu mull) und trotzdem haben diese Arbeit, wie erwartet. Der Schlüssel ist, um implizit die "OK" - oder(und) die "Abbrechen" - buttons. Habe es getestet und es funktioniert dankbar für mich. Der Zuhörer muß nicht gefeuert zweimal.
Blick auf dieses Beispiel,
InformationsquelleAutor der Antwort Crocodile