Android DatePicker.OnDateChangedListener调用了两次

Android DatePicker.OnDateChangedListener调用了两次,android,events,datepicker,Android,Events,Datepicker,我正在尝试创建一个应用程序,其中用户从日期选择器中选择一个日期,然后用一些值更新列表 我的GUI如下所示: <LinearLayout android:id="@+id/linearLayout1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" > <DatePic

我正在尝试创建一个应用程序,其中用户从日期选择器中选择一个日期,然后用一些值更新列表

我的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>
在CatLog中,我看到“TEST”字符串输出两次,每次我在小部件上玩+/-按钮时。有什么问题吗


注意:我故意“禁用”了列表更新代码,以确保问题与ListView无关,就像在

中一样,我仍然没有找到一个好的修复方法。我已经找到了一个解决方法,所以事件不会触发两次。解决办法如下:

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

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

}};

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

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

当我测试我的应用程序时,onDateSet方法在接受日期选择后调用了两次,在我取消选择时调用了一次

我在带有参数视图的onDateSet方法中添加了一个验证,如下所示

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

我希望你能为我服务,请在这里核对我的答案。它适用于TimePickerDialog,但也适用于DatePickerDialog。您可以创建一个自定义对话框,它几乎同样快速、简单,而且可以正常工作

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

    }
};

无需在Jelly beans下添加此代码

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

我没有使用onDateSet回调,而是覆盖了DatePickerDialog对话框的onClick方法,只处理按钮的点击

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

我创建了一个SupportDatePickerDialog.kt类

import android.app.DatePickerDialog
导入android.content.Context
导入android.os.Build
导入android.widget.DatePicker
导入androidx.appcompat.view.ContextThemeWrapper
/**
*支持[DatePickerDialog]
*用于解决Samsung 5[java.util.IllegalFormatConversionException]bug。
*>致命异常:java.util.IllegalFormatConversionException:%d无法格式化java.lang.String参数
* http://stackoverflow.com/a/31855744/570168
*对于OnDateSetListener,调用了两次bug
* https://stackoverflow.com/questions/12436073/datepicker-ondatechangedlistener-called-twice
*
*/
类SupportDateSetListener(私有val函数:(DatePicker,Int,Int)->Unit):DatePickerDialog.OnDateSetListener{
覆盖日期集(视图:日期选择器,年:整数,月:整数,月:整数){
if(view.isShown){
调用函数(视图、年、月、月)
}
}
}
类SupportDatePickerDialog(上下文:上下文,侦听器:SupportDateSetListener,年份:Int,月份:Int,dayOfMonth:Int):DatePickerDialog(固定上下文(上下文),侦听器,年,月,dayOfMonth){
伴星{
/**
*包装[上下文]以使用全息主题,避免三星设备上的愚蠢错误。
*/
@压制(“反对”)
私有上下文(上下文:上下文):上下文{
返回if(isBrokenSamsungDevice){
ContextThemeWrapper(上下文,android.R.style.Theme\u Holo\u Light\u对话框)
}否则{
上下文
}
}
/**
*受影响的设备:
*-三星5.0
*-三星5.1
*
*@如果设备受此错误影响,则返回true。
*/
@抑制(“拼写检查检查”)
private val isBrokenSamsungDevice:布尔值
get()=(Build.MANUFACTURER.equals(“samsung”,ignoreCase=true)
&&Build.VERSION.SDK\u INT>=Build.VERSION\u code.LOLLIPOP&&Build.VERSION.SDK\u INT
//待办事项
}、日历[日历.年]、日历[日历.月]、日历[日历.日/月])
supportDatePickerDialog.show()

谢谢您的回答,但这似乎并不能解决我的问题。我在更新显示方面没有问题。相反,我让显示更新了两次,而不是一次。请尝试以下操作…DatePickerDialog.OnDateSetListener mDateSetListener=new DatePickerDialog.OnDateSetListener(){public void onDateSet()(问题是datePicker.init接受datePicker.OnDateChangedListener作为最后一个参数,而不是DatePickerDialog.OnDateSetListener,因此它不起作用:SI发现问题与更新视图无关,而是与创建对话框时有关,因此如果要控制效果,则解决方法在于控制对话框的创建和可见性,这取决于你使用哪种方法来填充对话框你的答案是完美的…不需要创建额外的布尔变量来检查。这是一个hack;saved my day;coooool真正的问题是:到底为什么它会被调用两次?这是一个在Android 5.0中修复的错误,第早期版本没有后台。所以请使用此解决方法。错误:如果我们使用上述代码,android 5.0设备上是否存在任何问题?伙计,你必须接受@Cesardl答案并表现出一定的体育精神,因为此答案只是一个解决方法。ultimate catch bro@tomorI无法在同一问题上发布相同的答案。
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);
            }
        };
    }
}