Thursday, February 25, 2010

Creating a custom widget Calendar

In android, there is DatePicker and DatePickerDialog. But these two have lot of restrictions. So I decided to create a Calendar widget for one of my Android application.


The features of this calendar are,
- Set the startDate and endDate.
- Set a different color for dates that is coming outside the range of startDate and endDate.


Create two Spinners, one for Month and one for year. Create a TableLayout and add the TextView array, you can use buttons too, its up to you.

Creating spinner and adding values to it is straight forward. For year, from startDate and endDate, create the String array for year. MonthSpinner will be updated when you click on the startYear and endYear.

For creating spinner I created a function as,


public Spinner createSpinner(String[] results) {
Spinner spinner = new Spinner(ctContext);
ArrayAdapter adapter = new ArrayAdapter(ctContext,
android.R.layout.simple_spinner_item, results);
spinner.setAdapter(adapter);
return spinner;
}

Creating the spinner and add values to it for month and year as,


String[] months = new String[] { "January", "February", "March", "April",
"May", "June", "July", "August", "September", "October",
"November", "December" };
Spinner monthSpinner = createSpinner(months);

String[] rangeOfYears = new String[endYear - startYear + 1];
for (int iIndex = 0; iIndex < (endYear - startYear + 1); iIndex++) {
rangeOfYears[iIndex] = "" + tempStartYear;
tempStartYear++;
}
Spinner yearSpinner = createSpinner(rangeOfYears);


As I need a lot of textView for this application, created function as,


public TextView createTextView(String label, int width, int height,
float textSize, int textColor) {
TextView tv = new TextView(ctContext);
tv.setText(label);
tv.setWidth(width);
tv.setHeight(height);
tv.setTextSize(textSize);
tv.setTextColor(textColor);
return tv;
}

Creating textView in the tableLayout as,


TextView[] row = new TextView[49];
TableRow rowDate = new TableRow(ctContext);
for (int m = 0; m < 7; m++) {
rowDate = new TableRow(ctContext);
for (int n = 0; n < 7; n++) {
if (m == 0)
row[n] = createTextView(days[n], 30, 30, 14, 0xff00ff00);
else {
row[m * 7 + n] = createTextView(" ", 30, 30, 14, 0xff00ff00);
}
rowDate.addView(row1[m * 7 + n]);
}
layout.addView(rowDate);
}


Then for displaying days, I am using tableLayout with an array of TextViews. For getting the calendar date velues, I am using Georgian Calendar and for getting currentDate, using java.util.Calendar

I have a function called refreshCalendar(), that will be called everytime when you click on month or year spinner.

refreshCalendar() is the core of my Calendar application. I am passing month and the year value to this function, Then the GeorgianCalendar will create the corresponding calendar for me. This is also redrawing the calendar every time when click on month or year.


public void refreshCalendar(int year, int month) {
cal = new GregorianCalendar(year, month - 1, 1); // Create
nod = cal.getActualMaximum(GregorianCalendar.DAY_OF_MONTH);
som = cal.get(GregorianCalendar.DAY_OF_WEEK);
int dateLabel = 0;
for (int j = 1; j < 7; j++) {
for (int index = 0; index < 7; index++) {
if (j == 1 && (som - 1) > index) {
row1[j * 7 + index].setText(" ");
row1[j * 7 + index].setFocusable(false);
row1[j * 7 + index].setClickable(false);
} else if (((som - 1) <= index && j == 1) || j > 1) {
row1[j * 7 + index].setText(" " + (dateLabel + 1));
row1[j * 7 + index].setId((dateLabel + 1));
if (currentSelectedYear == endYear
&& currentSelectedMonth == endMonth
&& (dateLabel + 1) > endMonth) {
row1[j * 7 + index].setFocusable(false);
row1[j * 7 + index].setClickable(false);
} else if (currentSelectedYear == startYear
&& currentSelectedMonth == startMonth
&& (dateLabel + 1) < startDate) {
row1[j * 7 + index].setFocusable(false);
row1[j * 7 + index].setClickable(false);
} else {
row1[j * 7 + index].setFocusable(true);
row1[j * 7 + index].setClickable(true);
row1[j * 7 + index].setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Toast.makeText(ctContext," " + v.getId() + " mon : "+currentSelectedMonth+ " yr : "+ currentSelectedYear,Toast.LENGTH_SHORT).show();
}
});
dateLabel++;
}
if (dateLabel > nod) {
row1[j * 7 + index].setText(" ");
row1[j * 7 + index].setFocusable(false);
row1[j * 7 + index].setClickable(false);
}
}
}
}

No comments:

Post a Comment

Androidians