Как да направя слушател за бутон за отмяна на datepickers в Android?

Използвам инструмент за избор на дата в Android, за да позволя на потребителя да избере датата. Искам да направи едно нещо, ако потребителят избере дата и я зададе (при мен това работи добре) и след това да изчисти определено текстово поле, ако потребителят натисне бутона за отмяна на инструмента за избор на дата (отворете инструмента за избор на дата, но след това отменете от него).

Начинът, по който се опитвах, е като направих a

private DatePickerDialog.OnCancelListener mDateCancelListener =
    new DatePickerDialog.OnCancelListener() {
        public void onCancel(DialogInterface dialog) {
            timeClear(); //method that clears text field
        }

    };

тогава го правя

TimePickerDialog timeDialog = new TimePickerDialog(this,
  mTimeSetListener,
  c.get(Calendar.HOUR),
  c.get(Calendar.MINUTE),
  false);
timeDialog.setOnCancelListener(mTimeCancelListener);

за прикачване на слушателя.

Проблемът ми е, че слушателят работи, ако потребителят натисне бутона за връщане назад, но не и ако натисне бутона за отмяна. Опитах се да използвам слушател за отхвърляне и това работи, с изключение на факта, че изгасва дори независимо дали задам или отменя инструмента за избор на дата!

Какво трябва да направя, за да изгасне нещо, ако и само ако натисна бутона за отмяна на моя инструмент за избор на дата?


person Adam    schedule 26.06.2010    source източник
comment
Опитвам се да направя абсолютно същото, но с инструмента за избор на дата. В предложеното по-долу решение приложението се срива, защото .getButton(TimePickerDialog.BUTTON_NEGATIVE) връща нула. Някой има ли решение за това?   -  person Kenneth Baltrinic    schedule 21.11.2010
comment
Проверете това [1]: stackoverflow.com/questions/2928902/   -  person W00di    schedule 14.02.2013


Отговори (6)


Единственото решение, контраинтуитивно, е, че трябва да „замените“ бутона за отмяна:

    timeDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
            getString(R.string.cancel),
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    // do stuff
                }
            });
person EricLarch    schedule 11.08.2011
comment
Това извиква и метода OnTimeSet. Така че последователно извиква отрицателния слушател, след това положителния слушател. - person Ganesh Krishnan; 13.05.2015

Добре, след известно експериментиране открих, че това, което е необходимо, е OnDismissListener, както е показано по-долу. Имайте предвид, че разработих моето решение за TimePickerDialog, но setOnDismissListener е наследен от Dialog, така че трябва да работи по същия начин за DatePickerDialog.

timeDialog.setOnDismissListener(mOnDismissListener);


private DialogInterface.OnDismissListener mOnDismissListener =
    new DialogInterface.OnDismissListener() {
        public void onDismiss(DialogInterface dialog) {
            _logger.v("mOnDismissListener called");
            timeClear();
        }
    };

Тествах това и работи. Всъщност открих, че OnDismissListener се извиква и в двата сценария, които споменавате, когато потребителят щракне върху бутона Отказ и когато натисне хардуерния бутон за връщане назад. Така че имате нужда само от този манипулатор.

И накрая, след като вече знам какво да търся в Google, намерих тази статия, която описва разликата между OnDismissListener и OnCancelListener, в раздела за „Използване на Dismiss Listeners“:

person Kenneth Baltrinic    schedule 21.11.2010
comment
Това не е поисканото - onDismiss се задейства без значение какъв бутон е натиснат, но авторът иска да знае кога е натиснат бутонът за отмяна. Те също заявяват, че вече са изпробвали слушател onDismiss. - person barry; 11.11.2011
comment
@barry добра точка.. Това, което намирам за интересно е, че onCancelListener няма нищо общо с бутона Отказ в диалоговия прозорец на datePicker. Коментарът на W00di е правилният отговор... така че възможно дублиране. - person angryITguy; 13.10.2015

Можете да създадете една булева променлива isDataSet и в dateSetListener да изпълните isDataSet = true; и след това прикачете onDismissListener с такъв код:

if(isDataSet)
    //Data was set and neither back nor cancel button was clicked
else
    //back or cancel button was clicked

Но не забравяйте да зададете isDataSet = false всеки път, когато създавате диалогов прозорец.

person dilix    schedule 24.08.2012

Това е решението. Може да е полезно за някой друг

 datePickerDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "cancel", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            if (which == DialogInterface.BUTTON_NEGATIVE) {
                // do something
            }
        }
    });
person Amir    schedule 09.09.2015

Опитайте тази:

timeDialog.getButton(TimePickerDialog.BUTTON_NEGATIVE).setOnClickListener(mTimeCancelListener);

(Ще трябва да промените mTimeCancelListener, за да внедрите DialogInterface.OnClickListener вместо OnCancelListener)

person cristis    schedule 27.06.2010
comment
Благодаря за отговора! Все още имам малко проблеми. Ако направя DialogInterface.OnClickListener и се опитам да го използвам за TimePicker, той ми казва, че първо трябва да го кастя. Ако го направя, тогава програмата просто се срива, когато щракнете върху бутона за отваряне на TimePicker. Ако не го направите, тогава се казва setOnClickListener(android.view.View.OnClickListener) в android.view.View не може да се приложи към (android.content.DialogInterface.OnClickListener) timeDialog.getButton(TimePickerDialog.BUTTON_NEGATIVE).setOnClickListener(dateTimeClickCancelListener) ; - person Adam; 27.06.2010
comment
И се опитах да създам View.OnClickListner() вместо DialogInterfaceListener и програмата просто се срива, когато се опитам да отворя диалоговия прозорец TimePicker - person Adam; 27.06.2010

Пълното решение (тествано и работещо) е да комбинирате OnDismissListener (вижте отговор 3 на Kenneth Baltrinic по-горе) заедно с onDateSet boolean, описан от dilix (1 отговор по-горе). Имате нужда и от двете, защото onDismiss се използва във всички случаи: (1) потребителят е избрал действителни данни (2) потребителят е отменил (3) потребителят е натиснал хардуерен бутон за връщане назад.

Използването на комбинацията ви позволява да ги разграничите.

person PeteH    schedule 14.11.2012