Create your own datepicker in android using a single controller class

Posted By : Keshav Gupta | 17-Nov-2017

Android has its native date picker dialog.But you can also create your own datepicker dialog with your customized design.

Step1: Create a dialog class named as CustomDatePicker which will extend dialog and override its method.Layout file will be having three number picker years, month and day.There will be two buttons one for setting the date and one for cancel the dialog.

    private CustomTextView set;
    private CustomTextView cancel;
    private NumberPicker noPickerYear;
    private NumberPicker noPickerMonth;
    private NumberPicker noPickerDay;
    private CustomDatePickerListener listener;
    GregorianCalendar cal = new GregorianCalendar();
    public NumberPickerListener numberListener;

Here is CustomDatePickerListener which is an interface class for invoking the selected date to caller class.(Activity or Fragment).

Here is NumberPickerListener for handling calls on value change in Number picker.

Step2: Non instantiates the class using constructor calling and initialize views and assign memory to class.Code will be like this

   public CustomDatePickerDialog(@NonNull Context context, CustomDatePickerListener customDatePickerListener) {
        super(context);
        listener = customDatePickerListener;
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.customdatepicker);
        getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
        initViews();
        setEventListeners();
    }

    public void setEventListeners() {
        set.setOnClickListener(this);
        cancel.setOnClickListener(this);
        numberListener = new NumberPickerListener();
        noPickerMonth.setOnValueChangedListener(numberListener);
        noPickerYear.setOnValueChangedListener(numberListener);
    }
    private void initViews() {
        set = (CustomTextView) findViewById(R.id.buttonset);
        cancel = (CustomTextView) findViewById(R.id.buttonCancel);
        noPickerYear = (NumberPicker) findViewById(R.id.numberPickeryear);
        noPickerMonth = (NumberPicker) findViewById(R.id.numberPickermonth);
        noPickerDay = (NumberPicker) findViewById(R.id.numberPickerday);
    }

Step3: Configure all number pickers with their initials value.The code will be like this.

   public void setInitialDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int daysInMonth = calendar.getActualMaximum(Calendar.DATE); // 28
//        int maxdays=calendar.getActualMaximum(Calendar.DATE);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);

        Calendar todayCalendar = Calendar.getInstance();
        todayCalendar.setTime(Calendar.getInstance().getTime());
        int today = todayCalendar.get(Calendar.DAY_OF_MONTH);
//        int maxdays=calendar.getActualMaximum(Calendar.DATE);
        int todayYear = todayCalendar.get(Calendar.YEAR);
        int toDayMonth = todayCalendar.get(Calendar.MONTH);


        noPickerYear.setMaxValue(todayYear);
        noPickerYear.setMinValue(todayYear - 100);
        noPickerYear.setWrapSelectorWheel(false);
        noPickerYear.setValue(year);
        noPickerYear.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
        noPickerMonth.setMinValue(0);
        if (year == todayYear) {
            noPickerMonth.setMaxValue(toDayMonth);
            if (month > toDayMonth) {
                noPickerMonth.setValue(toDayMonth);
            }else{
                noPickerMonth.setValue(month);
            }
        } else {
            noPickerMonth.setValue(month);
            noPickerMonth.setMaxValue(11);
        }
        noPickerMonth.setDisplayedValues(new DateFormatSymbols().getMonths());
        noPickerMonth.setWrapSelectorWheel(false);
        noPickerMonth.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);

        noPickerDay.setMinValue(01);
        if (year == todayYear && month == toDayMonth && day == today) {
            noPickerDay.setMaxValue(today);
            noPickerDay.setValue(today);
        } else {
            noPickerDay.setMaxValue(daysInMonth);
            if (day > daysInMonth) {
                noPickerDay.setValue(daysInMonth);
            }else{
                noPickerDay.setValue(day);
            }
        }

        noPickerDay.setWrapSelectorWheel(false);
        noPickerDay.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
    }

Step4: Now we will call NumberPickerListener functionality that will update values on NumberPickers.The code will be like this.

  private class NumberPickerListener implements NumberPicker.OnValueChangeListener {

        /*@Override
        public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
            //your code
        }*/

        @Override
        public void onValueChange(NumberPicker numberPicker, int i, int i1) {
            int year;
            int month = 0;
            int day = 0;
            Calendar calendar;
            int daysInMonth = 0;
            GregorianCalendar presentCalendar = new GregorianCalendar(Calendar.getInstance().getTimeZone());
            int presentYear = presentCalendar.get(Calendar.YEAR);
            int presentMonth = presentCalendar.get(Calendar.MONTH);
            int presentDay = presentCalendar.get(Calendar.DAY_OF_MONTH);
            switch (numberPicker.getId()) {
                case R.id.numberPickeryear:
                    year = i1;
                    month = noPickerMonth.getValue();
//                day = noPickerDay.getValue();
//                calendar = new GregorianCalendar(year,month,1);
                    if (year == presentYear) {
                        noPickerMonth.setMaxValue(presentMonth);
                        if (month > presentMonth) {
                            noPickerMonth.setValue(presentMonth);
                        }
//                    daysInMonth = presentCalendar.getActualMaximum(Calendar.DAY_OF_MONTH); // 28

                    } else {
                        noPickerMonth.setMaxValue(11);
//                    daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); // 28
                    }
               /* if(day>daysInMonth) {
                    noPickerDay.setValue(daysInMonth);
                }
                noPickerDay.setMaxValue(daysInMonth);*/
                    numberListener.onValueChange(noPickerMonth, noPickerMonth.getValue(), noPickerMonth.getValue());

                    break;

                case R.id.numberPickermonth:
                    year = noPickerYear.getValue();
                    month = i1;
                    day = noPickerDay.getValue();
                    calendar = new GregorianCalendar(year, month, 1);
                    daysInMonth = calendar.getActualMaximum(Calendar.DATE); // 28
                    if (year == presentYear && month == presentMonth && (day == presentDay || day>presentDay)) {
                        noPickerDay.setMaxValue(presentDay);
                        noPickerDay.setValue(presentDay);
                    } else {
                        noPickerDay.setMaxValue(daysInMonth);
                        if (day > daysInMonth) {
                            noPickerDay.setValue(daysInMonth);
                        }
                    }
                    break;


            }
        }


    }

 

 

Step5:Now we will code click functionality for set date and cancel dialog and code to show dialog

    public void showDateDialog() {
        show();
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {

            case R.id.buttonset:
                SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
                Date date = new Date();
                String formattedTime = dateFormat.format(date);
                String pickerDay = String.format("%02d", noPickerDay.getValue());
                String strSelectedDate = pickerDay + "-" + (noPickerMonth.getValue() + 1) + "-" + noPickerYear.getValue() + "T" + formattedTime + "Z";
                listener.response(DateUtils.stringToDateTime(strSelectedDate));
                dismiss();
                break;

            case R.id.buttonCancel:
                dismiss();
                break;

        }
    }

The final code for this class will be like:

public class CustomDatePickerDialog extends Dialog implements View.OnClickListener {
    private CustomTextView set;
    private CustomTextView cancel;
    private NumberPicker noPickerYear;
    private NumberPicker noPickerMonth;
    private NumberPicker noPickerDay;
    private CustomDatePickerListener listener;
    GregorianCalendar cal = new GregorianCalendar();
    public NumberPickerListener numberListener;

    public CustomDatePickerDialog(@NonNull Context context, CustomDatePickerListener customDatePickerListener) {
        super(context);
        listener = customDatePickerListener;
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.customdatepicker);
        getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
        initViews();
        setEventListeners();
    }

    public void setEventListeners() {
        set.setOnClickListener(this);
        cancel.setOnClickListener(this);
        numberListener = new NumberPickerListener();
        noPickerMonth.setOnValueChangedListener(numberListener);
        noPickerYear.setOnValueChangedListener(numberListener);
    }
    private void initViews() {
        set = (CustomTextView) findViewById(R.id.buttonset);
        cancel = (CustomTextView) findViewById(R.id.buttonCancel);
        noPickerYear = (NumberPicker) findViewById(R.id.numberPickeryear);
        noPickerMonth = (NumberPicker) findViewById(R.id.numberPickermonth);
        noPickerDay = (NumberPicker) findViewById(R.id.numberPickerday);
    }
    public void setInitialDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int daysInMonth = calendar.getActualMaximum(Calendar.DATE); 
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);

        Calendar todayCalendar = Calendar.getInstance();
        todayCalendar.setTime(Calendar.getInstance().getTime());
        int today = todayCalendar.get(Calendar.DAY_OF_MONTH);

        int todayYear = todayCalendar.get(Calendar.YEAR);
        int toDayMonth = todayCalendar.get(Calendar.MONTH);


        noPickerYear.setMaxValue(todayYear);
        noPickerYear.setMinValue(todayYear - 100);
        noPickerYear.setWrapSelectorWheel(false);
        noPickerYear.setValue(year);
        noPickerYear.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
        noPickerMonth.setMinValue(0);
        if (year == todayYear) {
            noPickerMonth.setMaxValue(toDayMonth);
            if (month > toDayMonth) {
                noPickerMonth.setValue(toDayMonth);
            }else{
                noPickerMonth.setValue(month);
            }
        } else {
            noPickerMonth.setValue(month);
            noPickerMonth.setMaxValue(11);
        }
        noPickerMonth.setDisplayedValues(new DateFormatSymbols().getMonths());
        noPickerMonth.setWrapSelectorWheel(false);
        noPickerMonth.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);

        noPickerDay.setMinValue(01);
        if (year == todayYear && month == toDayMonth && day == today) {
            noPickerDay.setMaxValue(today);
            noPickerDay.setValue(today);
        } else {
            noPickerDay.setMaxValue(daysInMonth);
            if (day > daysInMonth) {
                noPickerDay.setValue(daysInMonth);
            }else{
                noPickerDay.setValue(day);
            }
        }

        noPickerDay.setWrapSelectorWheel(false);
        noPickerDay.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
    }



    public void showDateDialog() {
        show();
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {

            case R.id.buttonset:
                SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
                Date date = new Date();
                String formattedTime = dateFormat.format(date);
                String pickerDay = String.format("%02d", noPickerDay.getValue());
                String strSelectedDate = pickerDay + "-" + (noPickerMonth.getValue() + 1) + "-" + noPickerYear.getValue() + "T" + formattedTime + "Z";
                listener.response(DateUtils.stringToDateTime(strSelectedDate));
                dismiss();
                break;

            case R.id.buttonCancel:
                dismiss();
                break;

        }
    }


    private class NumberPickerListener implements NumberPicker.OnValueChangeListener {

     
        @Override
        public void onValueChange(NumberPicker numberPicker, int i, int i1) {
            int year;
            int month = 0;
            int day = 0;
            Calendar calendar;
            int daysInMonth = 0;
            GregorianCalendar presentCalendar = new GregorianCalendar(Calendar.getInstance().getTimeZone());
            int presentYear = presentCalendar.get(Calendar.YEAR);
            int presentMonth = presentCalendar.get(Calendar.MONTH);
            int presentDay = presentCalendar.get(Calendar.DAY_OF_MONTH);
            switch (numberPicker.getId()) {
                case R.id.numberPickeryear:
                    year = i1;
                    month = noPickerMonth.getValue();
//                day = noPickerDay.getValue();
//                calendar = new GregorianCalendar(year,month,1);
                    if (year == presentYear) {
                        noPickerMonth.setMaxValue(presentMonth);
                        if (month > presentMonth) {
                            noPickerMonth.setValue(presentMonth);
                        }
//                    daysInMonth = presentCalendar.getActualMaximum(Calendar.DAY_OF_MONTH); // 28

                    } else {
                        noPickerMonth.setMaxValue(11);
//                    daysInMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); // 28
                    }
               /* if(day>daysInMonth) {
                    noPickerDay.setValue(daysInMonth);
                }
                noPickerDay.setMaxValue(daysInMonth);*/
                    numberListener.onValueChange(noPickerMonth, noPickerMonth.getValue(), noPickerMonth.getValue());

                    break;

                case R.id.numberPickermonth:
                    year = noPickerYear.getValue();
                    month = i1;
                    day = noPickerDay.getValue();
                    calendar = new GregorianCalendar(year, month, 1);
                    daysInMonth = calendar.getActualMaximum(Calendar.DATE); // 28
                    if (year == presentYear && month == presentMonth && (day == presentDay || day>presentDay)) {
                        noPickerDay.setMaxValue(presentDay);
                        noPickerDay.setValue(presentDay);
                    } else {
                        noPickerDay.setMaxValue(daysInMonth);
                        if (day > daysInMonth) {
                            noPickerDay.setValue(daysInMonth);
                        }
                    }
                    break;


            }
        }


    }

}

Step6: Now to use this class in activity or fragment just instantiate this class and call its method.So code struct will be like.

 CustomDatePickerDialog customDatePickerDialog = new CustomDatePickerDialog(mContext, new CustomDatePickerListener() {
                    @Override
                    public void response(Date date) {
                        holder.mDateTv.setText(DateUtils.dateToString(date));
                        
                   }
                });
                customDatePickerDialog.setInitialDate(DateUtils.stringToDateTime(holder.mDateTv.getText().toString()));
                customDatePickerDialog.showYearDialog();

Here in below method, you need to send current date in Date object form as params in the method.Below there are also definitions  for string to DateTime() and CustomDatePickerListener class.So you will find like this and can use it.

   public static Date stringToDateTime(String dateString){
        SimpleDateFormat dateFormat= new SimpleDateFormat("HH:mm:ss");
        Date date = new Date();
        String formattedTime = dateFormat.format(date);
        String dtStart = dateString+"T"+formattedTime+"Z";
        SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy'T'HH:mm:ss'Z'");
        try {
            date = format.parse(dtStart);
            System.out.println(date);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return date;
    }

 

public interface CustomDatePickerListener {

    public void response(Date date);
}

 

   public static String dateToString(Date date) {
        SimpleDateFormat dateformat = new SimpleDateFormat("dd-MM-yyyy");
        String datetime = dateformat.format(date);
        System.out.println("Current Date Time : " + datetime);
        return datetime;
    }

That'll you have to do design your own datePicker.

 

 

About Author

Author Image
Keshav Gupta

Keshav Gupta is Android Developer in Oodles, he always look forward for new tasks and new things to learn more.

Request for Proposal

Name is required

Comment is required

Sending message..