Search code examples
javaandroiddatetimedatepickerandroid-calendar

android studio disable days from date picker


I want to disable some day from date picker I have an array that store the days I want to disable.

I have this code to disable the days from calendar

    for (Calendar loopdate = min_date_c;
                     min_date_c.before(max_date_c);
                     min_date_c.add(Calendar.DATE, 1), loopdate = min_date_c) {
                    int dayOfWeek = loopdate.get(Calendar.DAY_OF_WEEK);


                    if (dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.FRIDAY) {
                        Calendar[] disabledDays = new Calendar[1];
                        disabledDays[0] = loopdate;
                        datePickerDialog.setDisabledDays(disabledDays);
                    }
                }

and I tried this code to disable days that are stored in the arraylist, but it does not work. It only disables the first item from the arraylist

   ArrayList a=new ArrayList();
            a.add(1);  //saturday
            a.add(2);  //sunday
            a.add(3);  //monday
            int day;


            for(int i=0; i<a.size();i++) {

                day=(Integer)a.get(i);



                for (Calendar loopdate = min_date_c;
                     min_date_c.before(max_date_c);
                     min_date_c.add(Calendar.DATE, 1), loopdate = min_date_c) {
                    int dayOfWeek = loopdate.get(Calendar.DAY_OF_WEEK);



                    if (day == 1) {
                        System.out.println(day);
                        if (dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.FRIDAY) {
                            Calendar[] disabledDays = new Calendar[1];
                            disabledDays[0] = loopdate;
                            datePickerDialog.setDisabledDays(disabledDays);
                        }
                    }

                  else  if (day==2) {
                        System.out.println(day);

                        if (dayOfWeek == Calendar.SUNDAY || dayOfWeek == Calendar.FRIDAY) {
                            Calendar[] disabledDays = new Calendar[1];
                            disabledDays[0] = loopdate;
                            datePickerDialog.setDisabledDays(disabledDays);
                        }
                    }

                   else if (day==3) {
                        System.out.println(day);
                        if (dayOfWeek == Calendar.MONDAY || dayOfWeek == Calendar.FRIDAY) {
                            Calendar[] disabledDays = new Calendar[1];
                            disabledDays[0] = loopdate;
                            datePickerDialog.setDisabledDays(disabledDays);
                        }
                    }


                }

How do I fix this?


Solution

  • You can use the material design component MaterialDatePicker to control the calendar more easily and efficiently; it allows you to control every single day of the calendar by implementing CalendarConstraints.DateValidator interface.

    Specificlly in your issue, you need to disable particular days; so, you will create a class that implements CalendarConstraints.DateValidator, and then:

    • Override the needed methods, and build a Parcelable

    CalendarConstraints.DateValidator Extends Parcelable in order to maintain the DateValidator across device configuration changes. Parcelable breaks when passed between processes.

    • Override isValid(long date) method that validates every single date in the calendar and returns a boolean that indicates whether this date is valid or not, in other meaning if the date is enabled or disabled/dimmed; so, if a date is valid, then it returns true, and that date will be enabled for selection by the user.

    Hereunder, I will provide a Validator that disable Mondays in Feb.2020; and you can easily disable any days the same manner.

    Implementing CalendarConstraints.DateValidator:

    static class MondaysOutValidator implements CalendarConstraints.DateValidator {
    
        int mYear, mMonth, mDayOfWeek;
    
        MondaysOutValidator(int year, int month, int dayOfWeek) {
            mYear = year;
            mMonth = month;
            mDayOfWeek = dayOfWeek;
        }
    
        MondaysOutValidator(Parcel parcel) {
            mYear = parcel.readInt();
            mMonth = parcel.readInt();
            mDayOfWeek = parcel.readInt();
        }
    
    
        @Override
        public boolean isValid(long date) {
    
            List<Integer> allXDayOfMonth = getAllXDayOfMonth(mYear, mMonth, mDayOfWeek);
    
            boolean isValidDays = false;
            for (int xDay : allXDayOfMonth) {
                Calendar calendarStart = Calendar.getInstance();
                Calendar calendarEnd = Calendar.getInstance();
                ArrayList<Long> minDate = new ArrayList<>();
                ArrayList<Long> maxDate = new ArrayList<>();
                calendarStart.set(mYear, mMonth, xDay - 1);
                calendarEnd.set(mYear, mMonth, xDay);
                minDate.add(calendarStart.getTimeInMillis());
                maxDate.add(calendarEnd.getTimeInMillis());
                isValidDays = isValidDays || !(minDate.get(0) > date || maxDate.get(0) < date);
            }
    
            return !isValidDays;
    
        }
    
    
        private static int getFirstXDayOfMonth(int year, int month, int dayOfWeek) {
            Calendar cacheCalendar = Calendar.getInstance();
            cacheCalendar.set(Calendar.DAY_OF_WEEK, dayOfWeek);
            cacheCalendar.set(Calendar.DAY_OF_WEEK_IN_MONTH, 1);
            cacheCalendar.set(Calendar.MONTH, month);
            cacheCalendar.set(Calendar.YEAR, year);
            return cacheCalendar.get(Calendar.DATE);
        }
    
        private static List<Integer> getAllXDayOfMonth(int year, int month, int dayOfWeek) {
            final int ONE_WEEK = 7;
            int firstDay = getFirstXDayOfMonth(year, month, dayOfWeek);
            List<Integer> xDays = new ArrayList<>();
            xDays.add(firstDay);
    
            Calendar calendar = new GregorianCalendar(year, month, firstDay);
            calendar.add(Calendar.DAY_OF_MONTH, ONE_WEEK); // adding 1 Week
            while (calendar.get(Calendar.MONTH) == month) {
                xDays.add(calendar.get(Calendar.DAY_OF_MONTH));
                calendar.add(Calendar.DAY_OF_MONTH, ONE_WEEK); // adding 1 Week
            }
    
            return xDays;
        }
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(mYear);
            dest.writeInt(mMonth);
            dest.writeInt(mDayOfWeek);
        }
    
        public static final Parcelable.Creator<MondaysOutValidator> CREATOR = new Parcelable.Creator<MondaysOutValidator>() {
    
            @Override
            public MondaysOutValidator createFromParcel(Parcel parcel) {
                return new MondaysOutValidator(parcel);
            }
    
            @Override
            public MondaysOutValidator[] newArray(int size) {
                return new MondaysOutValidator[size];
            }
        };
    
    
    }
    

    Then use this validator to build CalendarConstraints in order to apply these constraints on the calendar dates

    /*
     * Limit selectable range to days other than Mondays of the month
     */
    private CalendarConstraints.Builder mondayDisableConstraints() {
        CalendarConstraints.Builder constraintsBuilderRange = new CalendarConstraints.Builder();
        constraintsBuilderRange.setValidator(new MondaysOutValidator(2020, Calendar.FEBRUARY, Calendar.MONDAY));
        return constraintsBuilderRange;
    }
    

    And finally build your MaterialDatePicker in your activity/fragment

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        MaterialDatePicker.Builder<Long> builderRange = MaterialDatePicker.Builder.datePicker();
        builderRange.setCalendarConstraints(mondayDisableConstraints().build());
        builderRange.setTitleText("Select Date Range");
        MaterialDatePicker<Long> pickerRange = builderRange.build();
        pickerRange.show(getSupportFragmentManager(), pickerRange.toString());
    
    }
    

    And this is the output:

    enter image description here

    Wish that can help you out, and welcome for further support.