DatePicker.OnDateChangedListener вызывается дважды

Я пытаюсь создать приложение, в котором пользователь выбирает дату из DatePicker, а затем список обновляется с некоторыми значениями.

Мой графический интерфейс выглядит следующим образом:

    <LinearLayout
    android:id="@+id/linearLayout1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center" >


    <DatePicker
        android:id="@+id/datePicker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

<LinearLayout
    android:id="@+id/linearLayout2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >



   <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1" >


    </ListView> 
</LinearLayout>

В то время как моя инициализация и обработка DatePicker выглядят следующим образом:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    datePicker = (DatePicker) findViewById(R.id.datePicker);

    Calendar c = Calendar.getInstance();

    year = c.get(Calendar.YEAR);
    month = c.get(Calendar.MONTH);
    day = c.get(Calendar.DAY_OF_MONTH);

    datePicker.init(year, month, day, dateSetListener);
}

private DatePicker.OnDateChangedListener dateSetListener = new DatePicker.OnDateChangedListener() {

    public void onDateChanged(DatePicker view, int year, int monthOfYear,
            int dayOfMonth) {
         Calendar c = Calendar.getInstance();
         c.set(year, monthOfYear, dayOfMonth);
         System.out.println ("TEST");

    }
};

В CatLog я вижу, что строка "TEST" выводится дважды, каждый раз, когда я играю с кнопками +/- виджета. В чем может быть проблема?

Примечание. Я специально отключил код для обновления списка, чтобы убедиться, что проблема не связана с ListView, как в здесь

Ответ 1

Когда я тестирую свое приложение, метод onDateSet вызывается дважды после принятия выбора даты и один раз, когда я отменил.

Я добавил проверку в методе onDateSet с представлением параметров, что-то вроде этого

@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth){
    if (view.isShown()) {
        updateDate(year, monthOfYear, dayOfMonth);
    }
}

Надеюсь, вы будете служить

Ответ 2

Мне все еще не удалось найти аккуратное исправление. Я скорее нашел обходное решение, поэтому событие не срабатывает дважды. Обходной путь выглядит следующим образом:

int timesCalled = 1;

private DatePicker.OnDateChangedListener dateSetListener = new DatePicker.OnDateChangedListener() {

public void onDateChanged(DatePicker view, int year, int monthOfYear,
        int dayOfMonth) {
     Calendar c = Calendar.getInstance();
     c.set(year, monthOfYear, dayOfMonth);
     timesCalled += 1;

     if ((timesCalled % 2) == 0) {
        System.out.println ("TEST");
     }

}};

Ответ 3

Вместо обратного вызова onDateSet я переопределил метод onClick в диалоговом окне DatePickerDialog и обрабатывал только клики BUTTON_POSITIVE.

public static class DatePickerFragment extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final Calendar c = Calendar.getInstance();
        int initialYear = c.get(Calendar.YEAR);
        int initialMonth = c.get(Calendar.MONTH);
        int initialDay = c.get(Calendar.DAY_OF_MONTH);
        return new DatePickerDialog(getActivity(), null, initialYear, initialMonth, initialDay) {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (which == BUTTON_POSITIVE) {
                    int year = getDatePicker().getYear();
                    int month = getDatePicker().getMonth();
                    int day = getDatePicker().getDayOfMonth();

                    //TODO: Do your logic here
                }
                super.onClick(dialog, which);
            }
        };
    }
}

Код остается ясным, но все же неясно, почему onDateSet вызывается дважды.

Ответ 4

private DatePicker.OnDateChangedListener dateSetListener = new DatePicker.OnDateChangedListener() { 

    public void onDateChanged(DatePicker view, int year, int monthOfYear, 
            int dayOfMonth) { 
         Calendar c = Calendar.getInstance(); 
         c.set(year, monthOfYear, dayOfMonth); 
         updateDisplay();

    } 
}; 


TextView datetext;
datetext = (TextView) findViewById(R.id.selected_date);


private void updateDisplay() {
        this.datetext.setText(new StringBuilder()
                // Month is 0 based so add 1
                .append(mMonth + 1).append("-").append(mDay).append("-")
                .append(mYear).append(" "));
    }

Ответ 5

Возможно, измените слушателя, добавив переменные экземпляра, таким образом, вы можете проверить, не отличаются ли они от последнего вызова метода:

final DatePickerDialog datePickerDialog = new DatePickerDialog (this, new DatePickerDialog.OnDateSetListener()
    {   
        private int year;
        private int month;
        private int day;

        @Override
        public void onDateSet (DatePicker view, int year, int monthOfYear, int dayOfMonth)
        {
            if (this.year == year && this.month == monthOfYear && this.day == dayOfMonth)
                return;

            this.year = year;
            this.month = monthOfYear;
            this.day = dayOfMonth;

            calendar.set (year, month, day);
            int index = officeCalendar.indexOfKey (calendar.getTimeInMillis ());

            if (index > -1)
                viewPager.setCurrentItem (index);
        }
    }, calendar.get (Calendar.YEAR), calendar.get (Calendar.MONTH), calendar.get (Calendar.DATE));

Ответ 6

private DatePicker.OnDateChangedListener dateSetListener = new DatePicker.OnDateChangedListener() {
    boolean fired = false;
    public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
         if (fired == true){
//Twince
         }
         else{
             Calendar c = Calendar.getInstance();
             c.set(year, monthOfYear, dayOfMonth);
             System.out.println ("TEST");
         }

    }
};

Ответ 7

Пожалуйста, проверьте мой ответ здесь. Это для TimePickerDialog, но также применимо к DatePickerDialog. Вы можете создать настраиваемый диалог, он почти одинаково быстрый и простой и просто работает.

fooobar.com/questions/116926/...

Ответ 8

Не нужно добавлять этот код под Jelly beans

@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth){
    if (view.isShown()) {
        updateDate(year, monthOfYear, dayOfMonth);
    }
}

Ответ 9

Имеет ту же проблему только в версии Android версии 4.2, она отлично работает с 2.2 (звонит слушателю даты только один раз). Я использую datepicker внутри диалогового фрагмента с обратным вызовом для действий. Чтобы "решить" проблему, я использовал одно и то же обходное решение, чем вы, поэтому я поддержал ваш ответ, так как я не нашел для него объяснений.