【问题标题】:Android datepicker min max date before api level 11api级别11之前的Android datepicker min max date
【发布时间】:2012-06-05 21:24:31
【问题描述】:

我正在尝试将 Android 中日期选择器的最小和最大日期设置为 API 级别 11 之前。我使用了以下代码:

mDatePickerField = startDatePickerDialog.getClass().getDeclaredField("mDatePicker");
mDatePickerField.setAccessible(true);

DatePicker startDatePickerInstance =(DatePicker)mDatePickerField.get(startDatePickerDialog);
startDatePickerInstance.init(mYearMin, mMonthMin, mDayMin, new DatePicker.OnDateChangedListener() {
    @Override
    public void onDateChanged(DatePicker datePicker, int i, int i1, int i2) {
        Date maxDate = new Date(mYearMax, mMonthMax, mDayMax, 0, 0, 0);
        Date selectedDate = new Date(i, i1, i2, 0, 0, 0);
        if (selectedDate.after(maxDate)) {
            datePicker.updateDate(mYearMax, mMonthMax, mDayMax);                                        
        }
    }
}

但是,updateDate 方法会再次触发 onDateChanged,并且日期选择器不会更新。
谁能帮忙解决这个问题?

【问题讨论】:

    标签: android android-datepicker


    【解决方案1】:

    您可以使用 init datePicker 方法设置范围。 最小值示例:

    // Calendar
    this.calendar = new GregorianCalendar();
    this.datePicker = (DatePicker) findViewById(R.id.xxxxx);
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        // (picker is a DatePicker)
        this.datePicker.setMinDate(this.calendar.getTimeInMillis());
    } else {
        final int minYear = this.calendar.get(Calendar.YEAR);
        final int minMonth = this.calendar.get(Calendar.MONTH);
        final int minDay = this.calendar.get(Calendar.DAY_OF_MONTH);
    
        this.datePicker.init(minYear, minMonth, minDay,
                new OnDateChangedListener() {
    
                    public void onDateChanged(DatePicker view, int year,
                            int month, int day) {
                        Calendar newDate = Calendar.getInstance();
                        newDate.set(year, month, day);
    
                        if (calendar.after(newDate)) {
                            view.init(minYear, minMonth, minDay, this);
                        }
                    }
                });
        Log.w(TAG, "API Level < 11 so not restricting date range...");
    }
    

    【讨论】:

    • newDate.after(calendar) 用于设置MAX Datecalendar.after(newDate) 用于设置MIN Date
    • 你知道如何同时使用 MIN 和 MAX,使用这种方法我似乎无法实现这一点
    • 您也可以使用反射获取归档stackoverflow.com/questions/10507607/…
    【解决方案2】:

    这个 DatePicker 自定义类允许我们指定最大和最小日期

    public class DatePickerDialogWithMaxMinRange extends DatePickerDialog {
    
     static int maxYear=2005; 
     static int maxMonth=11;
     static int maxDay=31;
    
     int minYear=1955;
     int minMonth=0;
     int minDay=1;
    
    
    public DatePickerDialogWithMaxMinRange(Context context,  OnDateSetListener callBack,int minYear,int minMonth,int minDay,int maxYear,int maxMonth,int maxDay) {
        super(context,callBack, maxYear, maxMonth, maxDay);
        this.minDay = minDay;
        this.minMonth = minMonth;
        this.minYear = minYear;
        DatePickerDialogWithMaxMinRange.maxDay = maxDay;
        DatePickerDialogWithMaxMinRange.maxMonth = maxMonth;
        DatePickerDialogWithMaxMinRange.maxYear = maxYear;
    }
    
    @Override
    public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
        super.onDateChanged(view, year, monthOfYear, dayOfMonth);
    
            if (year > maxYear ||monthOfYear > maxMonth && year == maxYear||
                     dayOfMonth > maxDay && year == maxYear && monthOfYear == maxMonth){
                view.updateDate(maxYear, maxMonth, maxDay);
                }else if(year < minYear ||monthOfYear < minMonth && year == minYear||
                     dayOfMonth < minDay && year == minYear && monthOfYear == minMonth){
                 view.updateDate(minYear, minMonth, minDay );
                }
    }
    

    }

    // 在您的 Activity 类或 Fragment 中使用此代码 指定成员为

    private int intCurrentYear;
    private int intCurrentMonth;
    private int intCurrentDay;
    private int intMaxYear;
    private int intMaxMonth;
    private int intMaxDay;
    private int intMinYear;
    private int intMinDay;
    private int intMinMonth;
    
        DatePickerDialogWithMaxMinRange datePickerDialog= null;
    DatePickerDialog.OnDateSetListener datePickerOnDateSetListener;
    Calendar myCalendar;
    

    // 在 onCreate 或任何你想调用的地方调用这个方法..

    注意:在 datepicker 对话框中选择后,您需要通过监听器自定义 datepickerdialog 来更新日期

    public void setDate() {
        /*
         * Initialise Listener for date set
         */
    
        datePickerOnDateSetListener = new DatePickerDialog.OnDateSetListener() {
            public void onDateSet(DatePicker view, int year, int monthOfYear,
                    int dayOfMonth) {
                edtTxtPlayerBirthDay.setText(new StringBuilder().append(year)
                        .append("-").append(monthOfYear + 1).append("-")
                        .append(dayOfMonth));
            }
        };
    
        // initialise DatePicker 
    
        myCalendar = Calendar.getInstance();
    
        intCurrentYear = myCalendar.get(Calendar.YEAR);
        intCurrentMonth = myCalendar.get(Calendar.MONTH);
        intCurrentDay = myCalendar.get(Calendar.DAY_OF_MONTH);
    
        intMaxYear =  intCurrentYear - 2000;
        intMaxMonth = intCurrentMonth;
        intMaxDay =  intCurrentDay;
    
        intMinYear =  intCurrentYear - 1950;
        intMinMonth = intCurrentMonth;
        intMinDay =  intCurrentDay; 
    
        datePickerDialog = new DatePickerDialogWithMaxMinRange(
                context, datePickerOnDateSetListener,intMinYear,intMinMonth,intMinDay,intMaxYear,intMaxMonth,intMaxDay);
    }
    

    在创建日期选择器时,根据您的要求传递 mindate 和 maxdate 用于在单击按钮时显示日期选择器或任何其他控件将此代码放入该 onclicklistener...

    datePickerDialog.show();
    

    【讨论】:

    • 老兄,你知道当你写 "abc" + 1 + object 它实际上是 new StringBUilder()... blah blah blah ...?正确的?那你为什么要手动写呢
    • @Ramesh 在 Android 5.0.1 中失败了,所以请提供一些替代解决方案。
    【解决方案3】:

    找到了一种很酷的方法来为DatePickerDialog 设置minmax 日期。适用于所有 Android 版本。只需根据Android版本返回DatePickerDialog

    protected Dialog onCreateDialog(int id)
    {
        switch ( id )
        {
            case DATE_DIALOG_ID:
                DatePickerDialog dialog = null;
                if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB )
                {
                    dialog = new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener()
                    {
                        @Override
                        public void onDateSet(DatePicker view, int selectedYear, int selectedMonth, int selectedDate)
                        {
                            mTextView.setText(selectedDate + "/" + selectedMonth + 1 + "/" + selectedYear);
                        }
                    }, year, month - 1, date);
                    Calendar currentDate = Calendar.getInstance();
                    dialog.getDatePicker().setMaxDate(currentDate.getTimeInMillis());
                    //If you need you can set min date too
                }
                else
                {
                    dialog = new DatePickerDialog(this, new DatePickerDialog.OnDateSetListener()
                    {
                        @Override
                        public void onDateSet(DatePicker view, int selectedYear, int selectedMonth, int selectedDate)
                        {
                            mTextView.setText(selectedDate + "/" + selectedMonth + 1 + "/" + selectedYear);
                        }
                    }, year, month - 1, date)
                    {
                        @Override
                        public void onDateChanged(DatePicker view, int year, int month, int day)
                        {
                            if ( year <= maxYear && month + 1 <= maxMonth && date <= maxDate ) //meets your criteria
                            {
                                view.updateDate(year, month, date); //update the date picker to selected date
                            }
                            else
                            {
                                view.updateDate(maxYear, maxMonth - 1, maxDate); // or you update the date picker to previously selected date
                            }
                        }
                    };
                }
                return dialog;
        }
        return null;
    }
    

    【讨论】:

      【解决方案4】:

      编辑您的 DatePicker.java,添加以下 3 个代码摘录。

      声明用于限制最小和最大日期的变量。

      // Variables for defining minimum date 
      private int minimumDay;
      private int minimumMonth;
      private int minimumYear;
      
      // Variables for defining maximum date 
      private int maximumDay;
      private int maximumMonth;
      private int maximumYear;
      

      在构造函数之后,你必须重写 onDateChanged 方法。

      // Called every time the user changes DatePicker values
      public void onDateChanged(DatePicker view, int year, int monthOfYear, 
              int dayOfMonth) {
      
          // Test if chosen date is before minimum date
          boolean beforeMinDate = false;
          boolean afterMaxDate = false;
      
          if(year < minimumYear){
              beforeMinDate = true;
          }
          else if(year == minimumYear){
              if(monthOfYear < minimumMonth){
                  beforeMinDate = true;
              }
              else if(monthOfYear == minimumMonth){
                  if(dayOfMonth < minimumDay){
                      beforeMinDate = true;
                  }
              }
          }
      
          // Test if chosen date is after maximum date
          if(!beforeMinDate){
              if(year > maxYear){
                  afterMaxDate = true;
              }
              else if(year == maxYear){
                  if(monthOfYear > maxMonth){
                      afterMaxDate = true;
                  }
                  else if(monthOfYear == maxMonth){
                      if(dayOfMonth > maxDay){
                          afterMaxDate = true;
                      }
                  }
              }
          }
      
          // If chosen date is before minimum date, update the date and internal
          // calendar to minimum date, else, check similarly fot the maximum
          // date, else, use the valid chosen date.
          if(beforeMinDate)
          {
              mCalendar.set(minimumYear, minimumMonth, minimumDay, 
                      mCalendar.get(Calendar.HOUR_OF_DAY), 
                      mCalendar.get(Calendar.MINUTE));
              updateDate(minimumYear, minimumMonth, minimumDay);
          }
          else if (afterMaxDate)
          {
              mCalendar.set(maximumYear, maximumMonth, maximumDay, 
                      mCalendar.get(Calendar.HOUR_OF_DAY), 
                      mCalendar.get(Calendar.MINUTE));
              updateDate(maximumYear, maximumMonth, maximumDay);
          }
          else
              mCalendar.set(year, monthOfYear, dayOfMonth, 
                      mCalendar.get(Calendar.HOUR_OF_DAY), 
                      mCalendar.get(Calendar.MINUTE));
      }
      

      现在,为最小和最大日期创建 setter 方法。

          // Method to define minimum permitted date for the picker.
          public void setMinimumDate(int minimumDay, int minimumMonth, 
                  int minimumYear)
          {
              this.minimumDay = minimumDay;
              this.minimumMonth = minimumMonth;
              this.minimumYear = minimumYear;
          }
      
          //Method to define maximum permitted date for the picker.
          public void setMaximumDate(int maximumDay, int maximumMonth, 
                  int maximumYear)
          {
              this.maximumDay = maximumDay;
              this.maximumMonth = maximumMonth;
              this.maximumYear = maximumYear;
          }
      

      第二部分,在您调用 DatePicker 对话框的活动中,您需要设置所需的最小和最大日期。下面的代码将当前日期设置为最小日期,将未来两年设置为最大日期。

          // Define current date as the minimum desired date
          Calendar c = Calendar.getInstance(); 
          int currentDay = c.get(Calendar.DAY_OF_MONTH);
          int currentMonth = c.get(Calendar.MONTH);
          int currentYear = c.get(Calendar.YEAR);
          inicioDateTimePicker.setMinimumDate(currentDay, currentMonth, 
                  currentYear);
      
          // Define two years in the future as the maximum desired date
          Calendar c = Calendar.getInstance(); 
          int currentDay = c.get(Calendar.DAY_OF_MONTH);
          int currentMonth = c.get(Calendar.MONTH);
          int currentYear = c.get(Calendar.YEAR);
          inicioDateTimePicker.setMinimumDate(currentDay, currentMonth, 
                  currentYear + 2);
      

      【讨论】:

        【解决方案5】:

        你不能。我处理这个问题的方法是对 DatePicker 使用 if 语句:

        import android.os.Build.*;
        
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            // (picker is a DatePicker)
            picker.setMinDate(...);
        } else {
            Log.w(TAG, "API Level < 11 so not restricting date range...");
        }
        

        我最终没有为 TimePicker 做任何事情。

        有什么好消息?

        SimonVT 已向后移植 DatePicker 和 TimePicker,因此您可以在早期 API 级别享受最新功能:

        【讨论】:

          【解决方案6】:

          根据@yostyle 的回答,我制作了一种方法来设置DatePicker 的最小和最大日期。 我的 DatePicker 在 AlertDialog 中使用,因为我需要一些额外的自定义,但是此方法可以直接用于任何 DatePickerDialog 或任何自定义 DatePicker:

          /**
               * Compat utility method that will set the minimum date and the maximum date for the DatePicker view.
               * <p/>
               * If the current API is greater than 11, than the normal {@link android.widget.DatePicker#setMinDate(long)} and
               * {@link android.widget.DatePicker#setMaxDate(long)} methods will be used.
               * <p/>
               *
               * @param minCalendar
               *         The minimum date for the picker
               * @param maxCalendar
               *         The maximum date for the picker
               */
              private void initDatePickerCompat(final Calendar minCalendar, final Calendar maxCalendar) {
                  if (null == mDatePicker) {
                      // Exit early if DatePicker view was not initialized
                      return;
                  }
                  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                      // (mDatePicker is a DatePicker)
                      mDatePicker.setMinDate(minCalendar.getTimeInMillis());
                      mDatePicker.setMaxDate(maxCalendar.getTimeInMillis());
                  } else {
                      final int minYear = minCalendar.get(Calendar.YEAR);
                      final int minMonth = minCalendar.get(Calendar.MONTH);
                      final int minDay = minCalendar.get(Calendar.DAY_OF_MONTH);
          
                      final int maxYear = maxCalendar.get(Calendar.YEAR);
                      final int maxMonth = maxCalendar.get(Calendar.MONTH);
                      final int maxDay = maxCalendar.get(Calendar.DAY_OF_MONTH);
          
                      mDatePicker.init(minYear, minMonth, minDay, new DatePicker.OnDateChangedListener() {
                          @Override
                          public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                              Calendar newCalendar = Calendar.getInstance();
                              newCalendar.set(year, monthOfYear, dayOfMonth);
          
                              if (newCalendar.after(maxCalendar)) {
                                  // MAX
                                  view.updateDate(maxYear, maxMonth, maxDay);
                              } else if (newCalendar.before(minCalendar)) {
                                  // MIN
                                  view.updateDate(minYear, minMonth, minDay);
                              } else {
                                  // BETWEEN
                                  view.updateDate(year, monthOfYear, dayOfMonth);
                              }
                          }
                      });
                  }
              }
          

          请记住,这个方法应该在 DatePicker 初始化之后调用,如下所示:

          mDatePicker = (DatePicker) view.findViewById(R.id.datePicker);
          mDatePicker.init(year, monthOfYear, dayOfMonth, this);
          DateTime minDate = new DateTime();
          DateTime maxDate = minDate.plusYears(10);
          // Set the minimum and the maximum date for the date picker
          initDatePickerCompat(minDate.toCalendar(Locale.getDefault()), maxDate.toCalendar(Locale.getDefault()));
          

          【讨论】:

            【解决方案7】:

            只需使用来自日历的 Value(Min & Max) 来设置 DatePiker.MaxDate & DatePiker.MinDate 尝试一些类似的东西:

             DatePickerDialog dialog = new DatePickerDialog();
            
             Java.Util.TimeZone GMT = new SimpleTimeZone(TimeZoneInfo.Local.BaseUtcOffset.Hours, "GMT"); 
             Calendar maxDate = Calendar.GetInstance(GMT);
             maxDate.Set(DateTime.Now.Year, DateTime.Now.Month - 1, DateTime.Now.Day);
            
             Calendar minDate = Calendar.GetInstance(GMT);
             minDate.Set(DateTime.Now.Year - 2, DateTime.Now.Month - 1, DateTime.Now.Day);
            
             dialog.DatePicker.MaxDate = maxDate.TimeInMillis;
             dialog.DatePicker.MinDate = minDate.TimeInMillis;
            

            【讨论】:

              猜你喜欢
              • 2011-11-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-05-16
              • 2023-03-12
              • 2020-11-01
              • 1970-01-01
              • 2020-03-05
              相关资源
              最近更新 更多