OnTimeSet called also when dismissing TimePickerDialog

北城余情 提交于 2019-12-29 05:41:06

问题


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?


回答1:


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();



回答2:


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...
        }
    }
};



回答3:


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.




回答4:


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);



回答5:


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.



来源:https://stackoverflow.com/questions/19452993/ontimeset-called-also-when-dismissing-timepickerdialog

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!