2012-12-30 14 views
6

O ile mi wiadomo, wersje przed Jelly Beans, miał Ustaw i Anuluj przycisków podczas korzystania TimePickerDialog. Jelly Beans ma tylko przycisk Zrobione.Czy istnieje sposób na anulowanie w Android JellyBean TimePickerDialog?

mogę tylko zostawić Sporządzono przycisk, a może zamknąć okno klikając na zewnątrz okna, ale mój onTimeSetListener jest wywoływana jeśli naciśnięcie Sporządzono lub na zewnątrz okna.

Tak więc znalazłem this stackoverflow question, który opisuje, że jest błąd podczas korzystania z DatePickerDialog. Aby naprawić problem przy użyciu DatePickerDialog, podczas inicjowania musiałem ustawić onDateSetListener na null i zaimplementować własne przyciski, aby obsłużyć metodę onClick: BUTTON_POSITIVE (Set) i (Cancel). Co jest w porządku, bo gdy przycisk Ustaw nazywa mogę uzyskać dostęp do datepicker wartości tak

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

Więc nie ma potrzeby korzystania onDateSetListener, ale jeśli będzie, to będzie znowu nazwać po naciśnięciu Ustaw lub anuluj.

Próbowałem użyć TimePickerDialog w ten sam sposób, ale problemem jest to, że wewnątrz BUTTON_POSITIVE metody onClick, nie może uzyskać dostępu do godziny i minuty wartości jak poprzednio, ponieważ TimePickerDialog nie przewiduje timepicker jak DatePickerDialog zapewnia DatePicker. I znowu, gdybym użył onTimeSetListener, zostałby wywołany przez naciśnięcie czegokolwiek.

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

Cóż, nadal można zarejestrować 'TimePickerDialog.OnTimeSetListener' w celu przechwytywania wprowadzonych wartości, ale po prostu nie robić nic z nimi, jeśli przycisk jest naciśnięty, prawda? –

+0

To jest problem, wywoływany OnTimeSetListener po naciśnięciu przycisku dodatniego, ujemnego i wstecznego. – Marko

+1

Miałem ten sam problem, zauważ, że zaakceptowana odpowiedź poniżej nie jest zgodna z poprzednimi wersjami (pre jb). Sice potrzebowałem sdk 8+, rozwiązałem go za pomocą wartości boolowskiej wewnątrz rozszerzonego okna dialogowego fragmentu i nadpisałem tutaj metodę onClick(). – auval

Odpowiedz

8

podstawie Twojego komentarza, powinno być dość łatwe do pilnowania OnTimeSetListener zwrotnego z logiczną, aby zapobiec uruchamianiu logiki w przypadku „Anuluj” jest kliknięty.

miałem szybką grę z kodem, oraz dodaje się wydawało do pracy w porządku:

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 
} 

Dla przykładu, ja założyć swoje PreferencesActivity narzędzi OnTimeSetListener. Od onTimeSet(...) jest wywoływana po onClick(...), można po prostu przełączać wartość logiczną, która określa, czy powinieneś coś zrobić z wartościami w wywołaniu zwrotnym, czy po prostu je zignorować.

Muszę się zgodzić, że nie jest idealny, ale przynajmniej funkcjonalny. Po wakacjach postaram się spojrzeć na "lepsze" rozwiązanie.

Jedną z alternatywnych opcji jest użycie odbicia, aby uzyskać uchwyt na wewnętrznie używanym widżecie TimePicker, ale jest to bardziej prawdopodobne w przyszłych wersjach Androida.


// Edycja: Potencjalna alternatywa?(Nie badane)

druga alternatywa, która może być nieco „czyszczenia”: extend TimePickerDialog i nadpisać (pusty) metoda public:

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

tam, śledzić godziny użytkownika ustawione dnia i minuty i implementuj dwa pobierające je zwracające. Następnie pobieraj te wartości z okna dialogowego tylko wtedy, gdy klikniesz przycisk "dodatni", ale po prostu "przerywaj" dla "Anuluj". Zasadniczo nie będziesz już potrzebował OnTimeSetListener, a zatem nie będzie miało znaczenia, czy kiedykolwiek zostanie wywołany, czy nie.


// Edit2: Wsparcie dla urządzeń pre-ICS

Po otrzymaniu kilka uwag o proponowane rozwiązanie nie działa na urządzeniach pre-ICS, zrobiłem małą zmianę w powyższym kodzie - nawet trudne było to poza pierwotnym pytaniem.

Główna różnica między urządzeniami pre-ICS i post-ICS polega na tym, że wywołanie zwrotne OnTimeSetListener nie jest automatycznie wywoływane po uruchomieniu metody (metod) przycisku dialogowego. Prostym sposobem obejścia tego problemu jest wywołanie metody onClick() w oknie dialogowym, które następnie wywoła odbiorcę. W powyższym rozwiązaniu dodałem kod wersji, ponieważ w przeciwnym razie Twój słuchacz zostanie dwukrotnie wywołany na urządzeniach post-ICS, co może prowadzić do niepożądanych efektów ubocznych.

Testowane i potwierdzone zachowanie w systemie Android 2.1-aktualizacja1 i systemie Android 4.2.2.

+0

Dziękuję za odpowiedź, spędź dzień bawiąc się kodem i wyszukując. Sztuczka z boolowskim działa dobrze. My PreferecesActivity nie implementuje OnTimeListener, ale mam pomysł. – Marko

+0

Działa to z 4.1, ale nie działa z 2.2 –

+1

@AdilMalik: po przeczytaniu niektórych komentarzy mówiących, że proponowane rozwiązanie nie działa na urządzeniach poprzedzających ICS, wprowadziłem niewielką zmianę, aby to uwzględnić. Więcej szczegółów można znaleźć w 2. edycji. –

1

Znalazłem ten wątek, gdy wystąpił ten sam problem "Tylko z przyciskiem" z TimePickerDialog dla Jelly Bean na moim Nexusie 7 (mój Nexus One, Gingerbread, mając przyciski Set i Cancel dla tego samego TimePickerDialog). Wydaje się jednak, że wraz z kolejną aktualizacją do wersji 4.3 Jelly Bean na moim Nexusie 7 (numer kompilacji JWR66Y), zwróciły się odpowiednie przyciski Set i Cancel.

W badaniu tego problemu natknąłem się jednak na tę Stackoverflow thread, która dość skrupulatnie przedstawia większe problemy z DatePickerDialog (z podobnymi problemami wskazanymi dla TimePickerDialog w odnośnym raporcie błędów) i oferuje rozwiązanie.

Należy pamiętać, że korzystanie z tych okien dialogowych należy uważnie rozpatrywać, ponieważ nie działają one prawidłowo w niektórych wersjach Androida (rozwiązanie oferowane we wspomnianym wątku nie jest używane "w kodzie produkcyjnym", zgodnie z jego autorem).

+0

Miło słyszeć, że problem został rozwiązany za pomocą najnowszej wersji. Dzięki – Marko

Powiązane problemy