android 日期选择器.OnDateChangedListener调用了两次

ozxc1zmp  于 2023-01-07  发布在  Android
关注(0)|答案(8)|浏览(154)

我正在尝试创建一个应用程序,其中用户从DatePicker中选择一个日期,然后使用一些值更新列表。
我的GUI如下所示:

<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无关,如here中那样

rwqw0loc

rwqw0loc1#

当我测试我的应用程序时,方法onDateSet在接受日期选择后调用了两次,在我取消选择时调用了一次。
我使用参数视图在方法onDateSet中添加了验证,如下所示

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

g0czyy6m2#

我仍然没有找到一个很好的解决方法。我找到了一个变通方法,这样事件就不会触发两次。变通方法如下:

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

}};
nbewdwxp

nbewdwxp3#

我重写了DatePickerDialog对话框的onClick方法,只处理BUTTON_POSITIVE单击,而不是onDateSet回调。

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被调用两次。

pieyvz9o

pieyvz9o4#

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(" "));
    }
x6h2sr28

x6h2sr285#

也许可以通过添加示例变量来修改侦听器,这样就可以检查它们是否与上次调用方法时不同:

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

j2datikz6#

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

    }
};
ymdaylpp

ymdaylpp7#

无需在Jelly bean下添加此代码

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

q9rjltbz8#

我创建了一个SupportDatePickerDialog.kt类

import android.app.DatePickerDialog
    import android.content.Context
    import android.os.Build
    import android.widget.DatePicker
    import androidx.appcompat.view.ContextThemeWrapper
    
    /**
     * Support [DatePickerDialog]
     * for working around Samsung 5 [java.util.IllegalFormatConversionException] bug.
     * > Fatal Exception: java.util.IllegalFormatConversionException: %d can't format java.lang.String arguments
     * http://stackoverflow.com/a/31855744/570168
     * for OnDateSetListener called twice bug
     * https://stackoverflow.com/questions/12436073/datepicker-ondatechangedlistener-called-twice
     *
     */
    
    
    
    class SupportDateSetListener(private val function: (DatePicker, Int, Int, Int) -> Unit) : DatePickerDialog.OnDateSetListener {
        override fun onDateSet(view: DatePicker, year: Int, month: Int, dayOfMonth: Int) {
            if (view.isShown) {
                function.invoke(view, year, month, dayOfMonth)
            }
        }
    }
    
    class SupportDatePickerDialog(context: Context, listener: SupportDateSetListener, year: Int, month: Int, dayOfMonth: Int) : DatePickerDialog(fixContext(context), listener, year, month, dayOfMonth) {
        companion object {
            /**
             * Wraps the [Context] to use the holo theme to avoid stupid bug on Samsung devices.
             */
            @Suppress("DEPRECATION")
            private fun fixContext(context: Context): Context {
                return if (isBrokenSamsungDevice) {
                    ContextThemeWrapper(context, android.R.style.Theme_Holo_Light_Dialog)
                } else {
                    context
                }
            }
    
            /**
             * Affected devices:
             * - Samsung 5.0
             * - Samsung 5.1
             *
             * @return true if device is affected by this bug.
             */
            @Suppress("SpellCheckingInspection")
            private val isBrokenSamsungDevice: Boolean
                get() = (Build.MANUFACTURER.equals("samsung", ignoreCase = true)
                        && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1)
        }
    }

用法:

val calendar = Calendar.getInstance()
val supportDatePickerDialog = SupportDatePickerDialog(this, SupportDateSetListener { datePicker: DatePicker, year: Int, month: Int, dayOfMonth: Int ->
    //TODO
}, calendar[Calendar.YEAR], calendar[Calendar.MONTH], calendar[Calendar.DAY_OF_MONTH])

supportDatePickerDialog.show()

相关问题