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 && 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.