9

I'm using a datepicker in Android to let the user to choose the date. I want it to do one thing if the user picks a date and sets it (I have that working fine) and then to clear a certain text field if the user pushes the cancel button on the datepicker (open up the datepicker but then cancel out of it).

The way I've been trying is by making a

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

    };

then I do

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

to attach the listener.

My problem is that the listener works if the user pushes the back button, but not if they push the cancel button. I tried using a dismiss listener, and that works, except for the fact that it goes off even whether I set or cancel the datepicker!

What do I need to do so something goes off if and only if I push the cancel button on my datepicker?

Adam
  • 91
  • 1
  • 1
  • 2
  • I am trying to do the exact same thing but with the date picker. In the proposed solution below, the app crashes because .getButton(TimePickerDialog.BUTTON_NEGATIVE) is returning null. Does anyone out there have a solution to this? – Kenneth Baltrinic Nov 21 '10 at 12:17
  • 1
    Check this [1]: http://stackoverflow.com/questions/2928902/can-we-get-cancel-click-listerner-of-datepicker-dialog – W00di Feb 14 '13 at 10:22

6 Answers6

5

The only solution, counter intuitive, is that you need to "override" the cancel button:

    timeDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
            getString(R.string.cancel),
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    // do stuff
                }
            });
EricLarch
  • 5,653
  • 5
  • 31
  • 37
2

You can create one boolean variable isDataSet and in dateSetListener perform isDataSet = true; and then attach onDismissListener with such a code:

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

But don't forget to set isDataSet = false each time you create a dialog.

dilix
  • 3,761
  • 3
  • 31
  • 55
2

Okay after some experimentation I have found that what is needed is an OnDismissListener as shown below. Note that I developed my solution for a TimePickerDialog, but setOnDismissListener is inherited from Dialog so it should work the same for a DatePickerDialog.

timeDialog.setOnDismissListener(mOnDismissListener);


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

I have tested this and it works. In fact, I have found that the OnDismissListener is called in both of the scenarios that you mention, when the user clicks the Cancel button and when they hit the hardware back button. So you only need this one handler.

Lastly, now that I know what to google for, I found this article that describes the difference between an OnDismissListener and an OnCancelListener, in the section on "Using Dismiss Listeners":

Kenneth Baltrinic
  • 2,941
  • 2
  • 28
  • 45
  • This isn't what was asked for - onDismiss is fired no matter what button is pressed, but the poster wants to know when the cancel button was pressed. They also state they have already tried an onDismiss listener. – barry Nov 11 '11 at 12:46
  • @barry good point.. What I find interesting is that the "onCancelListener" has nothing to do with the Cancel button on the datePicker dialog. W00di's comment is the correct answer... so possible duplicate. – angryITguy Oct 13 '15 at 03:09
1

This is the solution. It may helpful for someone else

 datePickerDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "cancel", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            if (which == DialogInterface.BUTTON_NEGATIVE) {
                // do something
            }
        }
    });
Amir
  • 8,821
  • 7
  • 44
  • 48
0

The full solution (tested and working) is to combine the OnDismissListener (see Kenneth Baltrinic's answer 3 above) together with the onDateSet boolean described by dilix (1 answer above). You need both because the onDismiss is used in all cases: (1) user has selected actual data (2) user has canceled (3) user has hit hardware back button.

Using the combination enables you to differentiate between them.

PeteH
  • 1,870
  • 25
  • 23
0

Try this:

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

(You'll have to change mTimeCancelListener to implement DialogInterface.OnClickListener instead of OnCancelListener)

cristis
  • 1,986
  • 16
  • 22
  • Thanks for the response! I'm still having a little trouble. If I make a DialogInterface.OnClickListener and try to use it for the TimePicker, it tells me I need to cast it first. If I do, then the program just crashes when you click the button to open up the TimePicker. If you don't then it says setOnClickListener(android.view.View.OnClickListener) in android.view.View cannot be applied to (android.content.DialogInterface.OnClickListener) timeDialog.getButton(TimePickerDialog.BUTTON_NEGATIVE).setOnClickListener(dateTimeClickCancelListener); – Adam Jun 27 '10 at 18:03
  • And I tried creating a View.OnClickListner() instead of a DialogInterfaceListener, and the program just crashes when I try to open up the TimePicker dialog – Adam Jun 27 '10 at 18:14