javaandroidandroid-studio

How to disable some random days in MaterialDatePicker


Like in title my dates will completly random, the user will deliver this dates. And I have question how to disable this dates in MaterialDatePicker ? It must be MaterialDatePicker cous of I want to keep possibility of selecting date in range. What i found is in Main you can use like:

MaterialDatePicker materialDatePicker =
                        MaterialDatePicker.Builder.dateRangePicker()
                        .setCalendarConstraints(DaysOutOfValidate().build())
                        .setSelection(Pair.create(MaterialDatePicker.thisMonthInUtcMilliseconds(),MaterialDatePicker.todayInUtcMilliseconds())).build();

                        materialDatePicker.show(getSupportFragmentManager(), "S");

than in main also:

  private CalendarConstraints.Builder DaysOutOfValidate() {

        List<Date> listDates = new ArrayList<>();
        listDates.add(new Date(2023,Calendar.NOVEMBER,10));
        listDates.add(new Date(2023,Calendar.NOVEMBER,16));

        CalendarConstraints.Builder constraintsBuilderRange = new CalendarConstraints.Builder();
        constraintsBuilderRange.setValidator(new DaysOutOfValidate(listDates));
            Log.i("Inovked twice","Twice");

        return constraintsBuilderRange;
    }

next you write your ownValidator:

public class DaysOutOfValidate implements CalendarConstraints.DateValidator {

    int mYear, mMonth, mDayOfWeek;
    List<Date> dates;

    DaysOutOfValidate(int year, int month, int dayOfWeek) {
        mYear = year;
        mMonth = month;
        mDayOfWeek = dayOfWeek;
    }

    public DaysOutOfValidate(List<Date> dates) {
        this.dates = dates;
    }

    DaysOutOfValidate(Parcel parcel) {
        mYear = parcel.readInt();
        mMonth = parcel.readInt();
        mDayOfWeek = parcel.readInt();
    }


    @Override
    public boolean isValid(long date) {

        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

        Calendar calendar = Calendar.getInstance();
        calendar.set(2023,Calendar.NOVEMBER,16);

        Calendar calendar2 = Calendar.getInstance();
        calendar2.set(2023,Calendar.NOVEMBER,10);


        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTimeInMillis(date);

        Calendar[] calendars = new Calendar[2];
        calendars[0]= calendar;
        calendars[1]= calendar2;

        String s1 ="";

        String s2 = sdf.format(calendar1.getTimeInMillis());

        for (int i = 0; i < calendars.length; i++) {
            s1 = sdf.format(calendars[i].getTimeInMillis());
        }

        Log.i("What's inside",s1+"");
        Log.i("What's inside 2: ",s2+"");

        if (s1.equals(s2))
        {
            Log.i("Over here","properly");
            return false;

        }
        else {
            return true;
        }




    }


    @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<DaysOutOfValidate> CREATOR = new Parcelable.Creator<DaysOutOfValidate>() {

        @Override
        public DaysOutOfValidate createFromParcel(Parcel parcel) {
            return new DaysOutOfValidate(parcel);
        }

        @Override
        public DaysOutOfValidate[] newArray(int size) {
            return new DaysOutOfValidate[size];
        }
    };
}

In DaysOutOfValidate are many wrong line but most impornant is method "isValid" which return true if the date is the same as the given date. I can't find how excatly work isValid but what I noticed that works like loop but I can't give more than one date cous of when I give more than one date like in example i give 16 November 2023 and 10 November 2023 only the last would disabled (10 november 2023), I know why it's happend like that but I don't know how to go around it. How to make to give some random dates and disable them in Calendar. Thanks in advance.


Solution

  • In the method you are using now, only the last date is assigned to the s1 variable while looping in the isValid() function and only this date is disable.

    I changed the isValid() function by using Calendar. I also added two new methods. When I try it in my own locale, it works smoothly. I hope it works for you too.

            @Override
            public boolean isValid(long date) {
                Calendar calendarInput = Calendar.getInstance();
                calendarInput.setTimeInMillis(date);
    
                for (Calendar blockedDate : getBlockedDates()) {
                    if (areSameDay(calendarInput, blockedDate)) {
                        return false; // If it matches one of the blocked dates, return false.
                    }
                }
    
                return true; // If there is no match, the date is valid.
            }
    
            private List<Calendar> getBlockedDates() {
                List<Calendar> blockedDates = new ArrayList<>();
                Calendar nov10 = Calendar.getInstance();
                nov10.set(2023, Calendar.NOVEMBER, 10);
                blockedDates.add(nov10);
    
                Calendar nov16 = Calendar.getInstance();
                nov16.set(2023, Calendar.NOVEMBER, 16);
                blockedDates.add(nov16);
    
                return blockedDates;
            }
    
            private boolean areSameDay(Calendar cal1, Calendar cal2) {
                return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
                        cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR);
            }
    

    DatePicker Screenshot