Android datepicker min max date before api level 1

2019-01-05 03:19发布

I am trying to set the min and max date of the date picker in Android to before API level 11. I used the following code:

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

However, the updateDate method fires onDateChanged again and the date picker is not updated.
Can anyone help to solve the problem?

7条回答
迷人小祖宗
2楼-- · 2019-01-05 03:50

Edit your DatePicker.java adding the following 3 code excerpts.

Declare the variables used for limiting the minimum and maximum date.

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

After the constructors, your have to override onDateChanged method.

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

And now, create setter methods for the minimum and maximum dates.

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

Second part, in the activity you call the DatePicker dialog, you need to set the minimum and maximum desired dates. The code below sets the current date as minimum and two years in the future as the maximum date.

    // 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);
查看更多
我想做一个坏孩纸
3楼-- · 2019-01-05 03:56

This DatePicker custom class Allow us Specify Max and Min Date

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

}

// use this code in your Activity class or Fragment specify member as

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;

// call this method in onCreate or where ever u want to..

note: you need pass the listener custom datepickerdialog to update the date after select in datepicker dialog

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

when creating date picker pass the mindate and maxdate as per u r requirement for showing datepicker when button clicked or any other control put this code inside for that onclicklistener...

datePickerDialog.show();
查看更多
神经病院院长
4楼-- · 2019-01-05 03:56

Just Use Value(Min & Max) Comes From Calender to set DatePiker.MaxDate & DatePiker.MinDate try some thing like :

 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;
查看更多
SAY GOODBYE
5楼-- · 2019-01-05 03:58

You can set range with init datePicker method. Example with min value :

// 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...");
}
查看更多
Melony?
6楼-- · 2019-01-05 04:00

Based on @yostyle's answer, I've made a method which sets the minimum and maximum date for an DatePicker. My DatePicker was used inside an AlertDialog because I needed some extra customizations, but this method can be used directly on any DatePickerDialog or for any custom DatePicker's:

/**
     * 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);
                    }
                }
            });
        }
    }

Keep in mind that this method should be called after DatePicker was initialized, like this:

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楼-- · 2019-01-05 04:04

You can't. The way I dealt with this was by using an if statement for the DatePicker:

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

I ended up doing nothing for the TimePicker.

What's the good news?

SimonVT has backported both the DatePicker and TimePicker, so that you can enjoy the latest functionality on earlier API levels:

查看更多
登录 后发表回答