Android CalenderView in a Dialog

Using android 4.2 I will cover how to create a CalendarView component in a dialog, and how to run it from a Fragment. Firstly, create a new xml file, call it calendar_view.xml. This is a very simple layout which holds solely the CalendarView element with the id calendarView.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:android1="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="0dp"
    android:paddingLeft="18dp"
    android:paddingRight="20dp"  >

    <FrameLayout
        android:layout_width="275dp"
        android:layout_height="275dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" >

        <CalendarView
            android:id="@+id/calendarView"
            android:layout_width="275dp"
            android:layout_height="275dp"
            android:layout_gravity="top"/>
    </FrameLayout>

</RelativeLayout>

We want to create an EditText in our fragment, that when clicked will open the CalendarView in a dialog, and allow us to set the date, which when saved, will be written to the EditText. Add the following to your fragment.xml:

<EditText
        android:id="@+id/editTextDate"
        android:labelFor="@id/editTextDate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:drawableRight="@drawable/calendar"
        android:inputType="textCapSentences"
        android:hint="@string/textfield_hint_date"
        android:focusable="false"
        android:ems="10" />

Open the fragment.java you want to use and define the following variables right after your public class .. {

private EditText fieldTaskDate;
private String taskDate;
private Long taskDateLong;
private AlertDialog dateDialog;
private CalendarView cal;
private SimpleDateFormat sdf;

In your onViewCreated you want to define the elements in your view, in this case just an EditText, and create a setOnClickListener for the EditText.

fieldTaskDate = (EditText) getView().findViewById(R.id.editTextDate);
sdf = new SimpleDateFormat("dd MMM yyyy");

fieldTaskDate.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
                AlertDialog diaBox = dateDialogBox();
                diaBox.show();
                cal = (CalendarView) diaBox.findViewById(R.id.calendarView);

                if(fieldTaskDate.length() == 0){
                        //Use current date.
                        Calendar date = Calendar.getInstance();
                        String curDate = sdf.format(date.getTime());
                        dateDialog.setTitle(curDate);
                        taskDate = curDate;
                        taskDateLong = date.getTimeInMillis();

                } else if(fieldTaskDate.length() > 0){
                        //Use user inputted date.
                        String dateFromField = fieldTaskDate.getText().toString();
                        DateFormat formatter = new SimpleDateFormat("dd MMM yyyy");
                        long dateInLong;
                        try {
                                Date date2 = formatter.parse(dateFromField);
                                dateInLong = date2.getTime();
                                cal.setDate(dateInLong);
                                dateDialog.setTitle(dateFromField);
                                taskDate = dateFromField;
                                taskDateLong = dateInLong;
                        } catch (ParseException e) {
                                e.printStackTrace();
                        }
                }
                cal.setOnDateChangeListener(new OnDateChangeListener() {
                        @Override
                        public void onSelectedDayChange(CalendarView view, int year, int month, int dayOfMonth) {
                                String curDate = sdf.format(cal.getDate());
                                Log.d("USERLOG", "new Date: "+ curDate);
                                dateDialog.setTitle(curDate);
                                taskDate = curDate;
                                taskDateLong = cal.getDate();
                        }
                });
        }
});

Once that is done, you will need the AlertDialog method. The AlertDialog will be run ondiaBox.show(); in the above setOnClickListener.

private AlertDialog dateDialogBox() {
        LayoutInflater inflater = getActivity().getLayoutInflater();
        View view = inflater.inflate(R.layout.calendar_view, null);

        dateDialog = new AlertDialog.Builder(getActivity())
        .setTitle("Date")
        .setView(view)
        .setPositiveButton("Set Date", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                        java.util.GregorianCalendar gCal = new GregorianCalendar();
                        gCal.add( Calendar.DATE, -1 );
                        long lMillis = gCal.getTime().getTime();

                        if(taskDateLong != null &amp;&amp; taskDateLong < lMillis){
                                fieldTaskDate.setHint("Date cannot be in the past.");
                                fieldTaskDate.setText("");
                        } else {
                                fieldTaskDate.setHint(getString(R.string.textfield_hint_date));
                                fieldTaskDate.setText(taskDate);
                        }

                }
        })
        .setNeutralButton("Remove", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                        fieldTaskDate.setText("");
                }
        })

        .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int whichButton) {
                        //Don't do anything.
                }
        })
        .create();
        return dateDialog;
}

The above code will make sure that the date is not in the past. If the user does select a date in the past, a warning hint will be set in the EditText instead. The IDE will be warning you about certain imports, so add these to the top of the fragment.java file.