27

Today I was trying to use the TimePickerDialog but I noticed a couple of flaws.

  1. OnTimeSet is called also when the dialog is dismissed (by clicking outside, for example)
  2. OnTimeSet is called twice when the user taps the "Done" button

The API I'm using is 18.

Anyone else has experienced these problems? How did you solve them?

Alessandro Roaro
  • 4,260
  • 6
  • 26
  • 45

5 Answers5

36

You hould use already given method of View class:

new TimePickerDialog.OnTimeSetListener() {
    @Override
    public void onTimeSet(TimePicker view, int hour, int minute) {  
        if (view.isShown()) {
            // This method will return true only once...
        }
    }
};
Koopakiller
  • 2,679
  • 3
  • 27
  • 44
Ankur Chaudhary
  • 2,549
  • 3
  • 17
  • 30
16

Faced the exact same issue today. Could not figure out why this was happening, but found a simple solution:

Method onTimeSet() is called once when dialog is dismissed and is called twice when Done button is clicked. Either way, there is one unwanted call to onTimeSet(). So I decided to always ignore the first call.

Here's the code:

Calendar mcurrentTime = Calendar.getInstance();
int hour = mcurrentTime.get(Calendar.HOUR_OF_DAY);
int minute = mcurrentTime.get(Calendar.MINUTE);

TimePickerDialog mTimePicker;
mTimePicker = new TimePickerDialog(MainActivity.this, new TimePickerDialog.OnTimeSetListener() 
    {
        int callCount = 0;   //To track number of calls to onTimeSet()

        @Override
        public void onTimeSet(TimePicker timePicker, int selectedHour, int selectedMinute) 
        {
             if(callCount == 1)    // On second call
             {
                 timeString = selectedHour + ":" + selectedMinute + ":00";
                 Log.d("TEST", "Chosen time : "+ timeString);           
             }

             callCount++;    // Incrementing call count.

        }
    }, hour, minute, true);

    mTimePicker.setTitle("Pick Time");
    mTimePicker.show();
Tony
  • 1,974
  • 18
  • 30
  • I handled it the same way (are there others?), but I hate these Android bugs. Shouldn't you reset callCount to 0 when it is 1 by the way? – Alessandro Roaro Dec 12 '13 at 19:54
  • callCount need not be reset as a new instance of mTimePicker is created every time you open the date picker dialog. – Tony Dec 13 '13 at 07:59
  • Kind of weird that it is being called twice, but this is the default behaviour. This seems to be a cheap quick fix, definitely going to be using this. – kabuto178 Jul 08 '14 at 22:35
  • 3
    In samsung 4.0.4 version. onTimeSet() will be called only for one time. So , your logic will not work any more. You should put a version check over there. – Shanki Bansal Jan 29 '15 at 04:30
5

To reiterate: This is a confirmed bug in Android for multiple Dialog types. Two workarounds have already been suggested, saving the state in a (instance) variable or asking the Dialog if it isShown(). But isShown() seems to be unreliable in Android 4.0.4 and saving the state gets messy if you want to re-show the dialog.
A better solution is to save the state inside the Dialog itself, because it is the same instance that calls the method:

public void onDateSet(DatePicker picker, int year, int monthOfYear, int dayOfMonth) {
    if (picker.getTag() == null) {
        picker.setTag("TAGGED");
        // Only gets called once per Dialog
    }
}

It's clean and effective.

leondepeon
  • 2,757
  • 1
  • 15
  • 11
2

Using count to avoid it. when TimePickDialog was selected more than twice, it should also work well.

            TimePickerDialog tpd = new TimePickerDialog(this, new TimePickerDialog.OnTimeSetListener() {
            int count = 0;
            @Override
            public void onTimeSet(TimePicker view, int setHour, int setMinute) {
                if(count % 2 == 0) {
                   //set time here
                }
                count++;

            } }, hour, minute, true);
Moerdo
  • 21
  • 2
1

Thanks to Tony for posting a workaround. This works for most of the time but not always. We had released our app with this workaround (along with version checks); however this solution failed on Samsung Galaxy Note GT-8000 (Android 4.4.2). Default 4.4.2 devices have this bug and solution works however Samsung seems to have fixed this issue in 4.4.2 release so onTimeSet() is called only once that we ignore and second call never happened.

We are posting a solution that we applied today. Though I am not happy with the solution as it is another hack/workaround but it may help in scenarios where version check doesn't help and OEMs merge selective fixes.

Our earlier implementation was

                        if((android.os.Build.VERSION.SDK_INT >=
                            Build.VERSION_CODES.ICE_CREAM_SANDWICH) &&
                            (android.os.Build.VERSION.SDK_INT <
                                    Build.VERSION_CODES.LOLLIPOP)){
                        if(ccount == 1){
                            // Do Your Processing
                            count = 0;
                        }else{
                            // Ignore event. Bug in Android API
                            count++;
                        }
                    }else{
                        // Do Your Processing
                    }

Our New Implementation is

                        if((android.os.Build.VERSION.SDK_INT >=
                            Build.VERSION_CODES.ICE_CREAM_SANDWICH) &&
                            (android.os.Build.VERSION.SDK_INT <
                                    Build.VERSION_CODES.LOLLIPOP)){
                        StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
                        StackTraceElement e = stacktrace[4];
                        String methodName = e.getMethodName();
                        if(methodName.equals("onClick")){
                            // Do Your Processing
                        }else{
                            // Ignore event. Bug in Android API
                        }
                    }else{
                        // Do Your Processing
                    }

Hope it may help others.

Gailu
  • 101
  • 10