Android Simple Calendar


Alot of people have been annoyed with the lack of a simple native calendar on Android…and rightfully so! Having to sync personal calendar events with Google’s online calendar may not be everyone’s frenzy. Some personal calendar events …are just that ..personal…mmh!

I am aware of AnCal by Piotr Zagawa and the new Calendar contained in OpenIntents by Karl Ostmo. There are also the calendar widgets which decorate the phonetop. Clearly, these guys should be appreciated in terms of their effort in coming up with a native Android Calendar.

In this tutorial, I would like to provide a quick skeleton framework for creating your own native Android Calendar. Feel free to improve, customize and hack at mine!

Download: SimpleCalendarImp.zip

Features:
– Contains slots to show number of events per day

File: simple_calendar_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:background="@drawable/bg">

	<ImageView
		android:id="@+id/calendarToJournalButton"
		android:src="@drawable/add_entry_button_selector"
		android:gravity="left"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:paddingBottom="10dip">
	</ImageView>


	<Button
		android:id="@+id/selectedDayMonthYear"
		android:textColor="#FFFFFF"
		android:layout_gravity="center"
		android:textAppearance="?android:attr/textAppearanceMedium"
		android:background="@drawable/calendar_top_header"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content">
	</Button>

	<LinearLayout
		xmlns:android="http://schemas.android.com/apk/res/android"
		android:orientation="horizontal"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content">

		<ImageView
			android:id="@+id/prevMonth"
			android:src="@drawable/calendar_left_arrow_selector"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content">
		</ImageView>
		<Button
			android:id="@+id/currentMonth"
			android:layout_weight="0.6"
			android:textColor="#FFFFFF"
			android:textAppearance="?android:attr/textAppearanceMedium"
			android:background="@drawable/calendar_bar"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content">
		</Button>
		<ImageView
			android:id="@+id/nextMonth"
			android:src="@drawable/calendar_right_arrow_selector"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content">
		</ImageView>
	</LinearLayout>

	<LinearLayout
		android:layout_gravity="center"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content">
		<ImageView
			android:id="@+id/calendarheader"
			android:src="@drawable/blue_bg_with_text"
			android:layout_gravity="center"
			android:layout_width="fill_parent"
			android:layout_height="wrap_content">
		</ImageView>
	</LinearLayout>


	<GridView
		android:id="@+id/calendar"
		android:numColumns="7"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content">
	</GridView>

</LinearLayout>

File: day_gridcell.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:background="@drawable/calendar_button_selector">

	<Button
		android:id="@+id/calendar_day_gridcell"
		android:layout_gravity="center"
		android:textColor="#FFFFFF"
		android:background="@drawable/calendar_button_selector"
		android:textAppearance="?android:attr/textAppearanceMedium"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content">
	</Button>
	
	<TextView
		android:id="@+id/num_events_per_day"
		style="@style/calendar_event_style"
		android:layout_gravity="right"
		android:layout_width="10dip"
		android:layout_height="10dip">
	</TextView>
</RelativeLayout>

File: SimpleCalendarViewActivity.java

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;

public class SimpleCalendarViewActivity extends Activity implements OnClickListener
	{
		private static final String tag = "SimpleCalendarViewActivity";

		private ImageView calendarToJournalButton;
		private Button selectedDayMonthYearButton;
		private Button currentMonth;
		private ImageView prevMonth;
		private ImageView nextMonth;
		private GridView calendarView;
		private GridCellAdapter adapter;
		private Calendar _calendar;
		private int month, year;
		private final DateFormat dateFormatter = new DateFormat();
		private static final String dateTemplate = "MMMM yyyy";

		/** Called when the activity is first created. */
		@Override
		public void onCreate(Bundle savedInstanceState)
			{
				super.onCreate(savedInstanceState);
				setContentView(R.layout.simple_calendar_view);

				_calendar = Calendar.getInstance(Locale.getDefault());
				month = _calendar.get(Calendar.MONTH) + 1;
				year = _calendar.get(Calendar.YEAR);
				Log.d(tag, "Calendar Instance:= " + "Month: " + month + " " + "Year: " + year);

				selectedDayMonthYearButton = (Button) this.findViewById(R.id.selectedDayMonthYear);
				selectedDayMonthYearButton.setText("Selected: ");

				prevMonth = (ImageView) this.findViewById(R.id.prevMonth);
				prevMonth.setOnClickListener(this);

				currentMonth = (Button) this.findViewById(R.id.currentMonth);
				currentMonth.setText(dateFormatter.format(dateTemplate, _calendar.getTime()));

				nextMonth = (ImageView) this.findViewById(R.id.nextMonth);
				nextMonth.setOnClickListener(this);

				calendarView = (GridView) this.findViewById(R.id.calendar);

				// Initialised
				adapter = new GridCellAdapter(getApplicationContext(), R.id.calendar_day_gridcell, month, year);
				adapter.notifyDataSetChanged();
				calendarView.setAdapter(adapter);
			}

		/**
		 * 
		 * @param month
		 * @param year
		 */
		private void setGridCellAdapterToDate(int month, int year)
			{
				adapter = new GridCellAdapter(getApplicationContext(), R.id.calendar_day_gridcell, month, year);
				_calendar.set(year, month - 1, _calendar.get(Calendar.DAY_OF_MONTH));
				currentMonth.setText(dateFormatter.format(dateTemplate, _calendar.getTime()));
				adapter.notifyDataSetChanged();
				calendarView.setAdapter(adapter);
			}

		@Override
		public void onClick(View v)
			{
				if (v == prevMonth)
					{
						if (month <= 1)
							{
								month = 12;
								year--;
							}
						else
							{
								month--;
							}
						Log.d(tag, "Setting Prev Month in GridCellAdapter: " + "Month: " + month + " Year: " + year);
						setGridCellAdapterToDate(month, year);
					}
				if (v == nextMonth)
					{
						if (month > 11)
							{
								month = 1;
								year++;
							}
						else
							{
								month++;
							}
						Log.d(tag, "Setting Next Month in GridCellAdapter: " + "Month: " + month + " Year: " + year);
						setGridCellAdapterToDate(month, year);
					}

			}

		@Override
		public void onDestroy()
			{
				Log.d(tag, "Destroying View ...");
				super.onDestroy();
			}

		// ///////////////////////////////////////////////////////////////////////////////////////
		// Inner Class
		public class GridCellAdapter extends BaseAdapter implements OnClickListener
			{
				private static final String tag = "GridCellAdapter";
				private final Context _context;

				private final List<String> list;
				private static final int DAY_OFFSET = 1;
				private final String[] weekdays = new String[]{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
				private final String[] months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
				private final int[] daysOfMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
				private final int month, year;
				private int daysInMonth, prevMonthDays;
				private int currentDayOfMonth;
				private int currentWeekDay;
				private Button gridcell;
				private TextView num_events_per_day;
				private final HashMap eventsPerMonthMap;
				private final SimpleDateFormat dateFormatter = new SimpleDateFormat("dd-MMM-yyyy");

				// Days in Current Month
				public GridCellAdapter(Context context, int textViewResourceId, int month, int year)
					{
						super();
						this._context = context;
						this.list = new ArrayList<String>();
						this.month = month;
						this.year = year;

						Log.d(tag, "==> Passed in Date FOR Month: " + month + " " + "Year: " + year);
						Calendar calendar = Calendar.getInstance();
						setCurrentDayOfMonth(calendar.get(Calendar.DAY_OF_MONTH));
						setCurrentWeekDay(calendar.get(Calendar.DAY_OF_WEEK));
						Log.d(tag, "New Calendar:= " + calendar.getTime().toString());
						Log.d(tag, "CurrentDayOfWeek :" + getCurrentWeekDay());
						Log.d(tag, "CurrentDayOfMonth :" + getCurrentDayOfMonth());

						// Print Month
						printMonth(month, year);

						// Find Number of Events
						eventsPerMonthMap = findNumberOfEventsPerMonth(year, month);
					}
				private String getMonthAsString(int i)
					{
						return months[i];
					}

				private String getWeekDayAsString(int i)
					{
						return weekdays[i];
					}

				private int getNumberOfDaysOfMonth(int i)
					{
						return daysOfMonth[i];
					}

				public String getItem(int position)
					{
						return list.get(position);
					}

				@Override
				public int getCount()
					{
						return list.size();
					}

				/**
				 * Prints Month
				 * 
				 * @param mm
				 * @param yy
				 */
				private void printMonth(int mm, int yy)
					{
						Log.d(tag, "==> printMonth: mm: " + mm + " " + "yy: " + yy);
						// The number of days to leave blank at
						// the start of this month.
						int trailingSpaces = 0;
						int leadSpaces = 0;
						int daysInPrevMonth = 0;
						int prevMonth = 0;
						int prevYear = 0;
						int nextMonth = 0;
						int nextYear = 0;

						int currentMonth = mm - 1;
						String currentMonthName = getMonthAsString(currentMonth);
						daysInMonth = getNumberOfDaysOfMonth(currentMonth);

						Log.d(tag, "Current Month: " + " " + currentMonthName + " having " + daysInMonth + " days.");

						// Gregorian Calendar : MINUS 1, set to FIRST OF MONTH
						GregorianCalendar cal = new GregorianCalendar(yy, currentMonth, 1);
						Log.d(tag, "Gregorian Calendar:= " + cal.getTime().toString());

						if (currentMonth == 11)
							{
								prevMonth = currentMonth - 1;
								daysInPrevMonth = getNumberOfDaysOfMonth(prevMonth);
								nextMonth = 0;
								prevYear = yy;
								nextYear = yy + 1;
								Log.d(tag, "*->PrevYear: " + prevYear + " PrevMonth:" + prevMonth + " NextMonth: " + nextMonth + " NextYear: " + nextYear);
							}
						else if (currentMonth == 0)
							{
								prevMonth = 11;
								prevYear = yy - 1;
								nextYear = yy;
								daysInPrevMonth = getNumberOfDaysOfMonth(prevMonth);
								nextMonth = 1;
								Log.d(tag, "**--> PrevYear: " + prevYear + " PrevMonth:" + prevMonth + " NextMonth: " + nextMonth + " NextYear: " + nextYear);
							}
						else
							{
								prevMonth = currentMonth - 1;
								nextMonth = currentMonth + 1;
								nextYear = yy;
								prevYear = yy;
								daysInPrevMonth = getNumberOfDaysOfMonth(prevMonth);
								Log.d(tag, "***---> PrevYear: " + prevYear + " PrevMonth:" + prevMonth + " NextMonth: " + nextMonth + " NextYear: " + nextYear);
							}

						// Compute how much to leave before before the first day of the
						// month.
						// getDay() returns 0 for Sunday.
						int currentWeekDay = cal.get(Calendar.DAY_OF_WEEK) - 1;
						trailingSpaces = currentWeekDay;

						Log.d(tag, "Week Day:" + currentWeekDay + " is " + getWeekDayAsString(currentWeekDay));
						Log.d(tag, "No. Trailing space to Add: " + trailingSpaces);
						Log.d(tag, "No. of Days in Previous Month: " + daysInPrevMonth);

						if (cal.isLeapYear(cal.get(Calendar.YEAR)) && mm == 1)
							{
								++daysInMonth;
							}

						// Trailing Month days
						for (int i = 0; i < trailingSpaces; i++)
							{
								Log.d(tag, "PREV MONTH:= " + prevMonth + " => " + getMonthAsString(prevMonth) + " " + String.valueOf((daysInPrevMonth - trailingSpaces + DAY_OFFSET) + i));
								list.add(String.valueOf((daysInPrevMonth - trailingSpaces + DAY_OFFSET) + i) + "-GREY" + "-" + getMonthAsString(prevMonth) + "-" + prevYear);
							}

						// Current Month Days
						for (int i = 1; i <= daysInMonth; i++)
							{
								Log.d(currentMonthName, String.valueOf(i) + " " + getMonthAsString(currentMonth) + " " + yy);
								if (i == getCurrentDayOfMonth())
									{
										list.add(String.valueOf(i) + "-BLUE" + "-" + getMonthAsString(currentMonth) + "-" + yy);
									}
								else
									{
										list.add(String.valueOf(i) + "-WHITE" + "-" + getMonthAsString(currentMonth) + "-" + yy);
									}
							}

						// Leading Month days
						for (int i = 0; i < list.size() % 7; i++)
							{
								Log.d(tag, "NEXT MONTH:= " + getMonthAsString(nextMonth));
								list.add(String.valueOf(i + 1) + "-GREY" + "-" + getMonthAsString(nextMonth) + "-" + nextYear);
							}
					}

				/**
				 * NOTE: YOU NEED TO IMPLEMENT THIS PART Given the YEAR, MONTH, retrieve
				 * ALL entries from a SQLite database for that month. Iterate over the
				 * List of All entries, and get the dateCreated, which is converted into
				 * day.
				 * 
				 * @param year
				 * @param month
				 * @return
				 */
				private HashMap findNumberOfEventsPerMonth(int year, int month)
					{
						HashMap map = new HashMap<String, Integer>();
						// DateFormat dateFormatter2 = new DateFormat();
						//						
						// String day = dateFormatter2.format("dd", dateCreated).toString();
						//
						// if (map.containsKey(day))
						// {
						// Integer val = (Integer) map.get(day) + 1;
						// map.put(day, val);
						// }
						// else
						// {
						// map.put(day, 1);
						// }
						return map;
					}

				@Override
				public long getItemId(int position)
					{
						return position;
					}

				@Override
				public View getView(int position, View convertView, ViewGroup parent)
					{
						View row = convertView;
						if (row == null)
							{
								LayoutInflater inflater = (LayoutInflater) _context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
								row = inflater.inflate(R.layout.calendar_day_gridcell, parent, false);
							}

						// Get a reference to the Day gridcell
						gridcell = (Button) row.findViewById(R.id.calendar_day_gridcell);
						gridcell.setOnClickListener(this);

						// ACCOUNT FOR SPACING

						Log.d(tag, "Current Day: " + getCurrentDayOfMonth());
						String[] day_color = list.get(position).split("-");
						String theday = day_color[0];
						String themonth = day_color[2];
						String theyear = day_color[3];
						if ((!eventsPerMonthMap.isEmpty()) && (eventsPerMonthMap != null))
							{
								if (eventsPerMonthMap.containsKey(theday))
									{
										num_events_per_day = (TextView) row.findViewById(R.id.num_events_per_day);
										Integer numEvents = (Integer) eventsPerMonthMap.get(theday);
										num_events_per_day.setText(numEvents.toString());
									}
							}

						// Set the Day GridCell
						gridcell.setText(theday);
						gridcell.setTag(theday + "-" + themonth + "-" + theyear);
						Log.d(tag, "Setting GridCell " + theday + "-" + themonth + "-" + theyear);

						if (day_color[1].equals("GREY"))
							{
								gridcell.setTextColor(Color.LTGRAY);
							}
						if (day_color[1].equals("WHITE"))
							{
								gridcell.setTextColor(Color.WHITE);
							}
						if (day_color[1].equals("BLUE"))
							{
								gridcell.setTextColor(getResources().getColor(R.color.static_text_color));
							}
						return row;
					}
				@Override
				public void onClick(View view)
					{
						String date_month_year = (String) view.getTag();
						selectedDayMonthYearButton.setText("Selected: " + date_month_year);

						try
							{
								Date parsedDate = dateFormatter.parse(date_month_year);
								Log.d(tag, "Parsed Date: " + parsedDate.toString());

							}
						catch (ParseException e)
							{
								e.printStackTrace();
							}
					}

				public int getCurrentDayOfMonth()
					{
						return currentDayOfMonth;
					}

				private void setCurrentDayOfMonth(int currentDayOfMonth)
					{
						this.currentDayOfMonth = currentDayOfMonth;
					}
				public void setCurrentWeekDay(int currentWeekDay)
					{
						this.currentWeekDay = currentWeekDay;
					}
				public int getCurrentWeekDay()
					{
						return currentWeekDay;
					}
			}
	}

238 thoughts on “Android Simple Calendar

  1. Updated version at download link.
    Note: I have included the assets to maintain the calendar look & feel.

    However, the developer needs to implement following code to obtain Number of Events per Day:
    (I used ActiveRecord-Android, for connecting to SQLite, email me for the code)

    private HashMap findNumberOfEventsPerMonth(int year, int month)
    {
    HashMap map = new HashMap();
    // DateFormat dateFormatter2 = new DateFormat();
    //
    // String day = dateFormatter2.format(“dd”, dateCreated).toString();
    //
    // if (map.containsKey(day))
    // {
    // Integer val = (Integer) map.get(day) + 1;
    // map.put(day, val);
    // }
    // else
    // {
    // map.put(day, 1);
    // }
    return map;
    }

  2. This looks like just what I need to get started on my 1st app for android. If I manage to create anything useful, I would like to release my app under some kind of Free Software License.

    What license (if any) is this code released under?

  3. Hi,
    Thanks for your application, but while I’m trying to run it, it says “Could not find SimpleCalendarImp.apk!” can you help me please ?
    Thanks in advance.

    • Hi Sajdad,

      The apk is the android packaged file that is run on the emulator/ device. How may I ask are you running the project file?
      1. Start Eclipse IDE
      2. Right click “Import …” OR from the menu File -> Import ….
      3. Point to the downloaded and unzipped project
      4. Load the project.
      5. Check if there are any errors on loading and check the build path.
      6. Create a new AVD if necessary ( will run on Android 1.5 to 2.3 versions)
      7. Run the project!

      Hope that helps!
      If there are any probs that please send an email describing the prob.

      -w

  4. Hi,
    I want to implement the code into my application to retreive the date, but I can’t call the intent.
    Can someone help me plz…!
    (android verison 2.2)
    @Override
    public void onClick(View v) {
    Intent i = new Intent(v.getContext(), FullCalendar.class);
    startActivityForResult(i, 0);
    }

    • Hi Aikito,

      From your code, I see that you are intercepting an onClick event and want to call/launch the intent to view the FullCalendar class.

      So, something like this :

      public class YourClassActivity extends Activity implements OnClickListener
      {
      private ImageButton myCalendarButton;
      @Override
      public void onCreate( Bundle savedInstanceState)
      {
      super.onCreate(savedInstanceState);
      myCalendarButton= (ImageButton) this.findViewById( R.id.myCalendarButton); //From XML view layer

      //Bind your ImageButton to the EventListener
      myCalendarButton.setOnClickListener( this);
      }

      …….
      @Override
      public void onClick( View v)
      {
      Intent intent= new Intent( this, FullCalendar.class) ;
      startActivity( intent );
      }
      }

      Notes:
      If you have a scenario, where you click a button and launch the FullCalendar in the next view, then the above is what I usually use.

      1. Ensure that the button in the XML view layer is bounded to an OnClickListener in the Java code ie. the class Actvity implements the OnClickListener.
      2. Now bind the myCalendarButton to the event listener using the
      myCalendarButton.setOnClickListener( this);
      3. Override the onClick handler method and launch your new Intent from the current activity YourClassActivity ie. “this”

      v.getContext() …would refer the a UI component which should respond to the click event….it’s better to refer to the YourClassActivity or simple getApplicationContext().

      -W

  5. Hi w2davids,
    It doesn’t work!
    My application call a intent X, in the X intent I have a TextView
    When I click on the TextView it suppose to call the intend Calendar with result expectation [ startActivityForResult(intent, 0); ]

    This is a sample of my code :
    in xml :

    in java :
    public class X extends Activity {

    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.time_edit);
    setTitle(“Time Edit”);

    dateDiag = (TextView) findViewById(R.id.DateEdit);

    dateDiag.setOnClickListener(new OnClickListener(){
    @Override
    public void onClick(View v) {
    Intent intent = new Intent(v.getContext(), Calendar.class);
    startActivityForResult(intent , 0);
    }
    });
    }

  6. Hi w2Divids,

    haha sorry for all the trouble, is all my bad.
    At the beginning, I just forgot to add the new class in AndroidManifest!

  7. No probs…from your problem description I was unclear if the activity loaded successfully and just did not appear…or for some other reason.
    I sometimes forget to bind the events to button, so everything is working but its not listening..hahah

  8. Hi,

    I was looking for this for a long time! Thanks a lot ^^

    However, I have a little problem with the display of the current day. The current day number is displayed in dark blue in every month grid (For example, every 13th of each month is in dark blue).
    Actually, I just want to display as this in the current month.

    How do you think I can this?

  9. Hi again,

    For those who are interested, I found how to do what I wanted.
    In the GridCellAdapter constructor, replace :

    ” setCurrentDayOfMonth(calendar.get(Calendar.DAY_OF_MONTH)); ”
    by
    “if (month == calendar.get(Calendar.MONTH)+1){ setCurrentDayOfMonth(calendar.get(Calendar.DAY_OF_MONTH));
    }”

    That’s it!
    Thanks again for this app. It’s helping me a lot!

    Bye

  10. Thanks, very useful. Just needed to check that it was also the current month on the blue text for highlighting today’s date.

    if (i == getCurrentDayOfMonth() && currentMonth == todaysMonth – 1)

  11. Sorry, I am new to Android and I have 2 questions.
    1. I don’t see the part where you write an event to SQLite. Where should I put it?
    2. I see the part where you have to query for an event from SQLite but can you give a little example.

    Thanks in advance.

      • Can you please share the link where from I can download SQLite code or you can mail me the code at the below mentioned mail id

      • Can u please send me a code to add events to this calender(basically the SQLite part). if so it will be a great help for me. If u can’t post here, pls send it to my email address.(shanuli.sliit@gmail.com).

        Thanks.

  12. Hi david
    your calendar working fine. But I want to view my events from google calendar. I wrote code to add event to google calendar its working fine.
    Calendar cal = Calendar.getInstance();
    Intent event = new Intent(Intent.ACTION_EDIT);
    event.setType(“vnd.android.cursor.item/event”);
    //event.putExtra(“allDay”, true);
    //event.putExtra(“rrule”, “FREQ=YEARLY”);
    event.putExtra(“endTime”, cal.getTimeInMillis()+60*60*1000);
    event.putExtra(“title”, “”);
    startActivity(event);

    I want similar type of code to view my events from my calendar…
    if its possible please send me asap…
    thanks in adv:

  13. Hi,Thx for this great calender,it really help me alots in my diploma project,currently we are doing a calender appointment scheduling apps,can i ask you what is the log.d?

  14. you are a god send angel. i was so messed up in working with ancal that i had lost hope. plus my fellow iphone developer had found the same library from the apple website..so i was defending Andriod’s honor. thank you again.

  15. HI, This is really very nice post,
    Thanks for this,

    One more things, i want to every Sunday in Red Colour , and every 2nd and 4th Saturdays in Red Colour how it is possible

    Plz Help Me
    Hitesh 9998576657

  16. Hi,
    I want to display the button in the upper left corner of the days of the month and I want to put a picture next to the day.
    How can I do this?
    Thanks.

  17. Using hard coded number of month is an error. By doing this your calendar will be wrong on bisextil years. For exemple try february 2012, you display only 28 days whereas in 2012 february has 29 days.
    Anyway your article help me a lot ! Thanks

  18. Hi!

    THANK YOU for this calendar.

    I’ve got some questions to ask you about the code. Can I have your email please? I see you mention in the comments email me but I can’t see your email!

    Thanks.

  19. Hi …
    i am new to android, i want highlight multiple particular date in calendar. how can i achive this one.. can u help me please

  20. Pingback: 60 User Interface Calendar Inspirations and Downloads … « Helpful information Weblog

  21. Thank you for this very useful sample calendar.
    It helps me a lot.
    Is it okay if I had a problem later on developing this app, I will post it here?

      • Instead of commenting it out, change it to actually work
        if (cal.isLeapYear(cal.get(Calendar.YEAR)) && mm == 2) {
        ++daysInMonth;
        }

      • You must add this too.

        // Trailing Month days
        for (int i = 0; i ” + getMonthAsString(prevMonth) + ” ” + String.valueOf((daysInPrevMonth – trailingSpaces + DAY_OFFSET) + i + 1));
        list.add(String.valueOf((daysInPrevMonth – trailingSpaces + DAY_OFFSET) + i + 1) + “-GREY” + “-” + getMonthAsString(prevMonth) + “-” + prevYear);
        }
        else
        {
        Log.d(tag, “PREV MONTH:= ” + prevMonth + ” => ” + getMonthAsString(prevMonth) + ” ” + String.valueOf((daysInPrevMonth – trailingSpaces + DAY_OFFSET) + i));
        list.add(String.valueOf((daysInPrevMonth – trailingSpaces + DAY_OFFSET) + i) + “-GREY” + “-” + getMonthAsString(prevMonth) + “-” + prevYear);
        }
        }

        Thanks a lot for this calendar!

      • Please delete my previous post, it’s wrong.

        You must add this too.

        // Trailing Month days
        for (int i = 0; i ” + getMonthAsString(prevMonth) + ” ” + String.valueOf((daysInPrevMonth – trailingSpaces + DAY_OFFSET) + i + 1));
        list.add(String.valueOf((daysInPrevMonth – trailingSpaces + DAY_OFFSET) + i + 1) + “-GREY” + “-” + getMonthAsString(prevMonth) + “-” + prevYear);
        }
        else
        {
        Log.d(tag, “PREV MONTH:= ” + prevMonth + ” => ” + getMonthAsString(prevMonth) + ” ” + String.valueOf((daysInPrevMonth – trailingSpaces + DAY_OFFSET) + i));
        list.add(String.valueOf((daysInPrevMonth – trailingSpaces + DAY_OFFSET) + i) + “-GREY” + “-” + getMonthAsString(prevMonth) + “-” + prevYear);
        }
        }

        Thanks a lot for this calendar!

      • Last attempt. Please delete my previous posts, they’re wrong.
        You must add this too.

        // Trailing Month days
        for (int i = 0; i < trailingSpaces; i++)
        {
        if (cal.isLeapYear(cal.get(Calendar.YEAR)) && mm == Calendar.MARCH + 1)
        {
        list.add(String.valueOf((daysInPrevMonth – trailingSpaces + DAY_OFFSET) + i + 1) + "-GREY" + "-" + getMonthAsString(prevMonth) + "-" + prevYear);
        }
        else
        {
        list.add(String.valueOf((daysInPrevMonth – trailingSpaces + DAY_OFFSET) + i) + "-GREY" + "-" + getMonthAsString(prevMonth) + "-" + prevYear);
        }
        }

        Thanks a lot for this calendar!

    • @w2davids
      This error is really bad, zalez corrected it, can you update your code by replacing your if with zalez’s code.

      @Viketig
      Can you specify why we must add your code?

      • Viketig is absolutely correct, you do need that code. The reason is that, although Zalez’ solution does fix the current month (February 2012), if you check the next month (March 2012) the trailing days appear a day behind, meaning Wednesday shows up as the 28 when it has been correctly fixed to be the 29th as it is in February. Viketig’s code fixes that discrepancy, so with the two combined code snippets, there are no further errors in the leap year calculation.

  22. Pingback: Example Calendar App « Team DailyDo

  23. i cant run the project …. im learning andriod and i am new to this.. can any one tell me how to run this? there are so many errors in the activity file… it says:
    cactivity can not be resolved to a type….

  24. thnx alot for your for your project ,
    i dont want to use SQLite ,
    cant i put the events of some selected days in .xml file ?
    and then get them ? if it’s possible what the code would be ?

    thnx for ur help in advance

  25. I’m having a weird problem where the greyed out days for the next and previous months use the num_events for the current month days. So, if the user’s current month is December and the 30th has an event, it will show November as having an event on the 30th even if there is not.

    I’ll try and fix it, but I’m hoping someone has already done so! Thanks

  26. Pingback: Add events to this Calender | Software development support, software risk,bugs for bugs, risk analysis,

    • OK, I think I solved it (dirty way, but it seems to work! ;) )

      Inside getview() I wrote down this code:
      currentMonth = (Button) CalendarioActivity.this.findViewById(R.id.currentMonth);
      String mycurrentMonth = currentMonth.getText().toString();
      String[] arr = mycurrentMonth.split(“\\s|,”);

      In this way I store the String “December” (the current month) in arr[0].

      Now I modified the line :
      if (eventsPerMonthMap.containsKey(theday) )
      into
      if (eventsPerMonthMap.containsKey(theday) && themonth.equals(arr[0]) )

      SEEMS to work! ;)

      • it didn’t work for me, I just don’t understand the word after mycurrentMonth.split(“blabla”)
        does anyone want to help me?
        thanks.

  27. I have a problem about implement this calendar.
    the first problem is on February 2012, the date is shown as 28, that should be 29, but it still consistent in March that the 1st date is begin on Thursday.
    the second problem is when the 1st date begin on Saturday, the 31st date is not shown, because the default row is 5.
    Please help.
    thank you.
    IgnatiusAdityaSetyadi@yahoo.com

  28. Sorry, It already works well on me.

    But I have another problem when I try it on my Android phone.
    When It run in portrait, the calendar header (Sun, Mon, Tue, Wed, Thu, Fri, Sat) show good, but not match when we try to rotate in landscape, maybe it because the Calendar header is just an image.
    Does anyone want to help me to solve this problem? at least try to change the calendar header from image that can be match in portrait or landscape.

    Thanks in advance.

  29. i am developing a program . where it has a calender , when the user presses on the date the event shows up .

    please anyone post the code for adding events to a date (for above program)

  30. What if I want to display the dates from the right to the left?
    Such as:
    {.. ,9,8,7,6,4,3,2,1}
    instead of:
    {1,2,3,4,5,6,7,8,9,…}
    Thanks a lot.

  31. What if I want the dates to appear from right to left.
    Such as {…9,8,7,6,5,4,3,2,1} instead of {1,2,3,4,5,6,7,8,9,..}
    What should I change in the code?
    Thanks.

  32. Good article, but FileFactory is horrible place to place your download. You just can’t download it unless you buy their premium service. Down Vote for that.

  33. Hello,
    Thank you for a wonderful calendar view.
    I found small issue with it. In case year is leap, it added one additional day to January, but not to February.
    Find a string
    if (cal.isLeapYear(cal.get(Calendar.YEAR)) && mm == 1)
    and replace it with
    if (cal.isLeapYear(cal.get(Calendar.YEAR)) && mm == 2)

  34. Pingback: Android Calendar with Jewish calendar dates, holidays and zmanim – Moishe Beshkin

  35. Pingback: Android календарь с еврейскими датами, праздниками и зманим – Мойше Бешкин

  36. Pingback: Android DateSlider with Calendar View – Moishe Beshkin

  37. Pingback: Android Слайдер Даты с Calendar View – Мойше Бешкин

  38. I am trying to implement a regional calendar with custom months and days. So is it possible to tweak the gridview to display custom months and days of the week. Or does it require a new implementation of Calendar class?

    JFYI, the dates in my regional calendar can easily be calculated from a Gregorian calendar date. All I want is a custom display. Any suggestions?

  39. I am using this code for my tablet asus the screen is very big but it is normal in my htc phone, how can I solve the strecth problem thank you for your great job.

  40. Reporting bug in daysInPrevMonth. If the current month is march of 2012 the variable daysInPrevMonth is 28 wich is false becouse february in this date has 29 days. So i did this to calculate the days in previous month, and i think is more reliable.

    /**************************************************************************************/
    Calendar cal_day = new GregorianCalendar(prevYear, prevMonth, 1);
    daysInPrevMonth = cal_day.getActualMaximum(Calendar.DAY_OF_MONTH);

    Isnt the best solution but it works.
    Greetings.

    Raxxco

  41. OH i forgot … if you change your daysInPrevMonth variable

    Calendar cal_day = new GregorianCalendar(prevYear, prevMonth, 1);
    daysInPrevMonth = cal_day.getActualMaximum(Calendar.DAY_OF_MONTH);

    and you did this patch comented before

    // Trailing Month days
    for (int i = 0; i < trailingSpaces; i++)
    {
    if (cal.isLeapYear(cal.get(Calendar.YEAR)) && mm == Calendar.MARCH + 1)
    {
    list.add(String.valueOf((daysInPrevMonth – trailingSpaces + DAY_OFFSET) + i + 1) + "-GREY" + "-" + getMonthAsString(prevMonth) + "-" + prevYear);
    }
    else
    {
    list.add(String.valueOf((daysInPrevMonth – trailingSpaces + DAY_OFFSET) + i) + "-GREY" + "-" + getMonthAsString(prevMonth) + "-" + prevYear);
    }
    }

    You have to go back to original code.
    // Trailing Month days
    273 for (int i = 0; i ” + getMonthAsString(prevMonth) + ” ” + String.valueOf((daysInPrevMonth – trailingSpaces + DAY_OFFSET) + i));
    276 list.add(String.valueOf((daysInPrevMonth – trailingSpaces + DAY_OFFSET) + i) + “-GREY” + “-” + getMonthAsString(prevMonth) + “-” + prevYear);
    277 }

  42. I’m trying to add a layout to create and save an event to the calendar but I haven’t been able to do it. If you have an example or something that will help me modify the code to save and read events I will appreciate it.

  43. Pingback: android: Simple Calendar View – Moishe Beshkin

  44. Michelle,

    I was using activerecord-android developed by vladimir kroz.

    My model:

    package com.pfizer.android.model;
    
    import java.sql.Timestamp;
    
    import org.kroz.activerecord.ActiveRecordBase;
    import org.kroz.activerecord.Database;
    
    public class JournalEntry extends ActiveRecordBase
    	{
    		// public for AR-access
    		public int typeId;
    
    		public String noteText;
    		public Timestamp dateCreated;
    		public Timestamp dateModified;
    
    		public String title;
    		public String location;
    
    		public int injectionSiteId;
    
    		public String description;
    		public int severity;
    
    		public JournalEntry()
    			{
    				// EMPTY
    			}
    
    		public JournalEntry(Database db)
    			{
    				super(db);
    			}
    
    		public JournalEntry(JournalEntry ent)
    			{
    				this._id = ent._id;
    				this.typeId = ent.typeId;
    				this.noteText = ent.noteText;
    				this.dateCreated = ent.dateCreated;
    				this.dateModified = ent.dateModified;
    				this.title = ent.title;
    				this.location = ent.location;
    				this.injectionSiteId = ent.injectionSiteId;
    				this.description = ent.description;
    				this.severity = ent.severity;
    			}
    
    		@Override
    		public String toString()
    			{
    				return this.title;
    			}
    	}
    
    
    package com.pfizer.android.view.screens.notes;
    
    import java.sql.Timestamp;
    import java.util.Calendar;
    import java.util.Date;
    
    import org.kroz.activerecord.ActiveRecordBase;
    import org.kroz.activerecord.ActiveRecordException;
    import org.kroz.activerecord.Database;
    import org.kroz.activerecord.DatabaseBuilder;
    
    import android.app.Activity;
    import android.app.Dialog;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.view.Window;
    import android.view.WindowManager;
    import android.view.View.OnClickListener;
    import android.view.inputmethod.InputMethodManager;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ImageView;
    import android.widget.RelativeLayout;
    import android.widget.Toast;
    
    import com.pfizer.android.R;
    import com.pfizer.android.config.DatabaseConfig;
    import com.pfizer.android.model.JournalEntry;
    import com.pfizer.android.model.JournalEntryTypeIF;
    import com.pfizer.android.model.ModelEntryUtils;
    import com.pfizer.android.utils.DateUtils;
    import com.pfizer.android.utils.Validate;
    import com.pfizer.android.view.components.DateTimePicker;
    import com.pfizer.android.view.components.HelpDialog;
    import com.pfizer.android.view.screens.journal.JournalOverviewScreen;
    
    public class AddNoteEntryScreen extends Activity implements OnClickListener
      {
        private static final String tag = "AddNoteEntryScreen";
        private Date selectedDate;
    
        // VALIDATION
        private boolean hasSelectedDate = false;
        private boolean hasSelectedNotesText = false;
    
        // Database
        private DatabaseBuilder _builder = null;
        private ActiveRecordBase _ARconn = null;
    
        // UI
        private ImageView saveEntryButton;
        private ImageView helpButton;
    
        private Button noteDateButton;
        private ImageView addNotesBanner;
        private EditText notesText;
        private ImageView deleteEntryButton;
    
        /**
         * Sets-up the SQLite database
         * 
         * @throws ActiveRecordException
         */
        private void setUpDatabase() throws ActiveRecordException
          {
            Log.d(tag, "setUpDatabase()");
    
            // Setup the builder
            _builder = new DatabaseBuilder(DatabaseConfig.DATABASE_NAME);
            Database.setBuilder(this._builder);
    
            Log.d(tag, "opening ActiveRecordBase");
            _ARconn = ActiveRecordBase.open(this, DatabaseConfig.DATABASE_NAME, DatabaseConfig.DATABASE_VERSION);
          }
    
        /**
         * Tears-down the SQLite database
         */
        private void tearDownDatabase()
          {
            // CLOSE DATBASE CONNECTION
            if (this._ARconn != null)
              {
                Log.d(tag, "Closing connection...");
                this._ARconn.close();
              }
          }
    
        /**
         * Retrieves the Request Parameters
         * 
         * @return
         */
        private Bundle getRequestParameters()
          {
            Log.d(tag, "Retrieving Request Parameters...");
            Bundle extras = getIntent().getExtras();
            if (extras != null)
              {
                Log.d(tag, "Bundle Extras:= " + extras.toString());
              }
            return extras;
          }
    
        @Override
        public void onCreate(Bundle savedInstanceState)
          {
            Log.d(tag, "Creating View ...");
            super.onCreate(savedInstanceState);
            setTitle("Notes");
    
            // Sets the View Layer
            setContentView(com.pfizer.android.R.layout.add_note_entry);
    
            // PREVENT SOFTWARE KEYBOARD FROM AUTOMATICALLY POPPING-UP
            getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
    
            // Establish Database Connection
            try
              {
                setUpDatabase();
              }
            catch (ActiveRecordException e)
              {
                e.printStackTrace();
              }
    
            // Save Entry Button
            saveEntryButton = (ImageView) this.findViewById(R.id.saveEntryButton);
            saveEntryButton.setOnClickListener(this);
    
            // Help
            helpButton = (ImageView) this.findViewById(R.id.helpButton);
            helpButton.setOnClickListener(this);
    
            // Date/Time
            noteDateButton = (Button) this.findViewById(R.id.notesTimeButton);
            noteDateButton.setOnClickListener(this);
    
            // Banner
            addNotesBanner = (ImageView) this.findViewById(R.id.add_note_banner);
    
            // EditText Notes
            notesText = (EditText) this.findViewById(R.id.notesText);
            InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(notesText.getWindowToken(), 0);
    
          }
    
        // @Override
        public void onClick(View view)
          {
            if (view == noteDateButton)
              {
                this.showDateTimeDialog();
              }
            if (view == saveEntryButton)
              {
                hasSelectedNotesText = Validate.presenceOf(notesText.getText().toString());
                if (hasSelectedDate && hasSelectedNotesText)
                  {
                    saveEntry();
                  }
                else
                  {
                    Toast.makeText(getApplicationContext(), "Please enter Date & Notes text!", Toast.LENGTH_LONG).show();
                  }
              }
            if (view == helpButton)
              {
                final HelpDialog helpDialog = new HelpDialog(this, R.layout.help_dialog_note);
                helpDialog.show();
    
                // Dismiss/Cancel Button
                ImageView dismissButton = (ImageView) helpDialog.findViewById(R.id.dismissButton);
                dismissButton.setOnClickListener(new OnClickListener()
                  {
                    @Override
                    public void onClick(View v)
                      {
                        helpDialog.dismiss();
                      }
                  });
              }
          }
    
        /**
         * Saves the Entry
         */
        private void saveEntry()
          {
            try
              {
                JournalEntry entry = _ARconn.newEntity(JournalEntry.class);
               
    
                // DEFAULT TO CURRENT DATE
                if (getSelectedDate() != null)
                  {
                    entry.dateCreated = new java.sql.Timestamp(getSelectedDate().getTime());
                    entry.dateModified = entry.dateCreated;
                  }
                else
                  {
                    Calendar calendar = Calendar.getInstance();
                    entry.dateCreated = new Timestamp(calendar.getTimeInMillis());
                    entry.dateModified = entry.dateCreated;
                  }
    
                // VALIDATION
                boolean hasNotesText = Validate.presenceOf(notesText.getText().toString());
                if (hasNotesText)
                  {
                    entry.noteText = notesText.getText().toString();
                  }
                else
                  {
                    entry.noteText = "";
                  }
                
                entry.typeId = JournalEntryTypeIF.NOTE;
                entry.title = entry.noteText;
                entry.description = entry.noteText;
                entry.location = ModelEntryUtils.EMPTY_FIELD;
    
    
                entry.save();
                Log.d(tag, entry.toString());
    
                // Reset the fields
                resetFields();
    
                // SWITCH TO JournalOverviewScreen SCREEN
                Log.d(tag, "Re-directing -> JournalOverviewScreen ...");
                goToJournalOverview();
              }
            catch (ActiveRecordException e)
              {
                e.printStackTrace();
              }
          }
    
        /**
         * Navigate to Appropriate EditScreen given a JournalEntry
         * 
         * @param journalEntry
         */
        private void goToJournalOverview()
          {
            Log.d(tag, "goToJournalOverview ...");
            Intent intent = null;
    
            Log.d(tag, "Re-directing -> JournalOverviewScreen ...");
            intent = new Intent(this, JournalOverviewScreen.class);
            startActivity(intent);
            finish();
            return;
          }
    
        /**
         * Select Date/Time
         */
        private void showDateTimeDialog()
          {
            // Create the dialog
            final Dialog mDateTimeDialog = new Dialog(this);
    
            // Inflate the root layout
            final RelativeLayout mDateTimeDialogView = (RelativeLayout) getLayoutInflater().inflate(R.layout.date_time_dialog, null);
    
            // Grab widget instance
            final DateTimePicker mDateTimePicker = (DateTimePicker) mDateTimeDialogView.findViewById(R.id.DateTimePicker);
    
            // Check is system is set to use 24h time (this doesn't seem to work as
            // expected though)
            final String timeS = android.provider.Settings.System.getString(getContentResolver(), android.provider.Settings.System.TIME_12_24);
            final boolean is24h = !(timeS == null || timeS.equals("12"));
    
            // Update demo TextViews when the "OK" button is clicked
            ((Button) mDateTimeDialogView.findViewById(R.id.SetDateTime)).setOnClickListener(new OnClickListener()
              {
    
                public void onClick(View v)
                  {
                    Date selectedDate = mDateTimePicker.getDate();
                    setSelectedDate(selectedDate);
                    noteDateButton.setText(DateUtils.convertDateToListItemFormat(getSelectedDate().getTime()));
                    hasSelectedDate = true;
                    mDateTimeDialog.dismiss();
                  }
              });
    
            // Cancel the dialog when the "Cancel" button is clicked
            ((Button) mDateTimeDialogView.findViewById(R.id.CancelDialog)).setOnClickListener(new OnClickListener()
              {
    
                public void onClick(View v)
                  {
                    hasSelectedDate = false;
                    mDateTimeDialog.cancel();
                  }
              });
    
            // Reset Date and Time pickers when the "Reset" button is clicked
            ((Button) mDateTimeDialogView.findViewById(R.id.ResetDateTime)).setOnClickListener(new OnClickListener()
              {
    
                public void onClick(View v)
                  {
                    // TODO Auto-generated method stub
                    mDateTimePicker.reset();
                  }
              });
    
            // Setup TimePicker
            mDateTimePicker.setIs24HourView(is24h);
            // No title on the dialog window
            mDateTimeDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            // Set the dialog content view
            mDateTimeDialog.setContentView(mDateTimeDialogView);
            // Display the dialog
            mDateTimeDialog.show();
          }
    
        /**
         * Reset UI Fields
         */
        private void resetFields()
          {
            this.noteDateButton.setText("Set Date/Time");
            this.notesText.setText("");
          }
    
        /**
         * 
         * @param selectedDate
         */
        public void setSelectedDate(Date selectedDate)
          {
            this.selectedDate = selectedDate;
          }
    
        /**
         * 
         * @return
         */
        public Date getSelectedDate()
          {
            return selectedDate;
          }
    
        @Override
        public void onDestroy()
          {
            String msg = "Destroying View!";
            Log.d(tag, msg);
            super.onDestroy();
    
            // Close Database Connection
            tearDownDatabase();
          }
      }
    
    package com.pfizer.android.model;
    
    import org.kroz.activerecord.ActiveRecordBase;
    import org.kroz.activerecord.Database;
    
    public class JournalEntryType extends ActiveRecordBase
    	{
    		// public for AR-access
    		public String name;
    
    		// journal_entry_types_array
    		public JournalEntryType()
    			{
    				// EMPTY
    			}
    
    		public JournalEntryType(Database db)
    			{
    				super(db);
    			}
    
    		@Override
    		public String toString()
    			{
    				return this.name;
    			}
    
    	}
    
    package com.pfizer.android.model;
    
    public interface JournalEntryTypeIF
    	{
    		public static final int ALL = 0;
    		public static final int APPOINTMENT = 1;
    		public static final int INJECTION = 2;
    		public static final int REACTION = 3;
    		public static final int NOTE = 4;
    		public static final int SYMPTOM = 5;
    		public static final int EMPTY= -1;
    	}
    
    
    
  45. Pingback: looking for a good datepicker calendar for android | PHP Developer Resource

  46. Pingback: » roll your own calendar widget My Blog

  47. i m getting error in this code it says nullpointerexeption error at gridcell.setText(theday);
    and i have done some research and i think the error at list can you plz help me
    here is my code

    package com.android.mycalender;

    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.GregorianCalendar;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Locale;

    import android.annotation.TargetApi;
    import android.app.Activity;
    import android.content.Context;
    import android.graphics.Color;
    import android.os.Bundle;
    import android.text.format.DateFormat;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.View.OnClickListener;
    import android.widget.BaseAdapter;
    import android.widget.Button;
    import android.widget.GridView;
    import android.widget.ImageView;
    import android.widget.TextView;
    @TargetApi(3)
    public class mycalender extends Activity implements OnClickListener {

    private Calendar _calendar;
    private int month,year;
    private ImageView privmonth;
    private ImageView nextmonth;
    private Button currentMonth;
    private GridView calendarview;
    private final DateFormat dateFormatter = new DateFormat();
    private Button selectedDayMonthYearButton;
    private GridCellAdapter adapter;

    private static final String dateTemplate = “MMMM yyyy”;
    @TargetApi(3)
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mycalender_view);

    _calendar = Calendar.getInstance(Locale.getDefault());
    month = _calendar.get(Calendar.MONTH)+1;
    year = _calendar.get(Calendar.YEAR);

    selectedDayMonthYearButton = (Button) this.findViewById(R.id.selectedDayMonthYear);
    selectedDayMonthYearButton.setText(“Selected: “);

    privmonth = (ImageView) this.findViewById(R.id.privmonth);
    privmonth.setOnClickListener(this);

    currentMonth = (Button) this.findViewById(R.id.currentmonth);
    currentMonth.setText(DateFormat.format(dateTemplate, _calendar.getTime()));

    nextmonth = (ImageView) this.findViewById(R.id.nextmonth);
    nextmonth.setOnClickListener(this);

    calendarview = (GridView) this.findViewById(R.id.calendar);

    adapter = new GridCellAdapter(getApplicationContext(), R.id.daygridcell, month, year);
    adapter.notifyDataSetChanged();
    calendarview.setAdapter(adapter);
    }

    /**
    *
    * @param month
    * @param year
    */
    @TargetApi(3)
    private void setGridCellAdapterToDate(int month, int year)
    {
    adapter = new GridCellAdapter(getApplicationContext(), R.id.daygridcell, month, year);
    _calendar.set(year, month – 1, _calendar.get(Calendar.DAY_OF_MONTH));
    currentMonth.setText(DateFormat.format(dateTemplate, _calendar.getTime()));
    adapter.notifyDataSetChanged();
    calendarview.setAdapter(adapter);
    }

    public void onClick(View v)
    {
    if(v == privmonth)
    {
    if (month 11)
    {
    month = 1;
    year++;
    }
    else
    {
    month++;
    }
    setGridCellAdapterToDate(month, year);
    }
    }
    @Override
    public void onDestroy()
    {

    super.onDestroy();
    }

    public class GridCellAdapter extends BaseAdapter
    {

    private final List list;
    private final String[] months ={“January”, “February”, “March”, “April”, “May”, “June”, “July”, “August”, “September”, “October”, “November”, “December”};
    private final int[] daysofmonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    private int month;
    private int year;
    private int daysinmonth;
    private Context _context;
    private Button gridcell;
    private HashMap eventsPerMonthMap;
    private TextView num_events_per_day;
    private Calendar cal;
    private int trailingSpaces;
    private int daysInPrevMonth;
    private static final int DAY_OFFSET = 1;
    private int prevMonth;
    private String prevYear;
    private int currentDayOfMonth;
    private String nextYear;
    private int currentWeekDay;

    public GridCellAdapter(Context _context,int textViewResourceId, int month, int year)
    {
    super();
    this._context= _context;
    this.list = new ArrayList();
    this.month= month;
    this.year=year;

    Calendar calendar = Calendar.getInstance();
    setCurrentDayOfMonth(calendar.get(Calendar.DAY_OF_MONTH));
    setCurrentWeekDay(calendar.get(Calendar.DAY_OF_WEEK));

    printmonth(month, year);

    // Find Number of Events
    eventsPerMonthMap = findnumberofeventpermonth(year, month);

    }
    private void setCurrentDayOfMonth(int currentDayOfMonth) //this
    {
    this.currentDayOfMonth = currentDayOfMonth;
    }
    public void setCurrentWeekDay(int currentWeekDay)
    {
    this.currentWeekDay = currentWeekDay;
    }
    public int getCurrentWeekDay()
    {
    return currentWeekDay;
    }
    private void printmonth(int mm, int yy)
    {
    int trailingSpaces = 0;
    int leadSpaces = 0;
    int daysInPrevMonth = 0;
    int prevMonth = 0;
    int prevYear = 0;
    int nextMonth = 0;
    int nextYear = 0;
    int currentmonth = mm-1;
    String currentmonthname= getmonthasstring(currentmonth);
    daysinmonth = getnumberofdaysinmonth(currentmonth);

    // Gregorian Calendar : MINUS 1, set to FIRST OF MONTH
    GregorianCalendar cal = new GregorianCalendar(yy, currentmonth, 1);

    if (currentmonth == 11)
    {
    prevMonth = currentmonth – 1;
    daysInPrevMonth = getnumberofdaysinmonth(prevMonth);
    nextMonth = 0;
    prevYear = yy;
    nextYear = yy + 1;

    }
    else if (currentmonth == 0)
    {
    prevMonth = 11;
    prevYear = yy – 1;
    nextYear = yy;
    daysInPrevMonth = getnumberofdaysinmonth(prevMonth);
    nextMonth = 1;

    }
    else
    {
    prevMonth = currentmonth – 1;
    nextMonth = currentmonth + 1;
    nextYear = yy;
    prevYear = yy;
    daysInPrevMonth = getnumberofdaysinmonth(prevMonth);

    }
    int currentWeekDay = cal.get(Calendar.DAY_OF_WEEK) – 1;
    trailingSpaces = currentWeekDay;

    if (cal.isLeapYear(cal.get(Calendar.YEAR)) && mm == 1)
    {
    ++daysinmonth;
    }

    // Trailing Month days
    for (int i = 0; i < trailingSpaces; i++)
    {
    list.add(String.valueOf((daysInPrevMonth – trailingSpaces + DAY_OFFSET) + i) + "-GREY" + "-" + getmonthasstring(prevMonth) + "-" + prevYear);
    }

    // Current Month Days
    for (int i = 1; i <= daysinmonth; i++){
    if (i == getCurrentDayOfMonth())
    {
    list.add(String.valueOf(i) + "-BLUE" + "-" + getmonthasstring(currentmonth) + "-" + yy);
    }
    else
    {
    list.add(String.valueOf(i) + "-WHITE" + "-" + getmonthasstring(currentmonth) + "-" + yy);
    }
    }

    // Leading Month days
    for (int i = 0; i < list.size() % 7; i++)
    {

    list.add(String.valueOf(i + 1) + "-GREY" + "-" + getmonthasstring(nextMonth) + "-" + nextYear);
    }

    }
    public int getCurrentDayOfMonth()
    {
    return currentDayOfMonth;
    }

    private HashMap findnumberofeventpermonth( int year, int month)
    {
    HashMap Map = new HashMap();
    return Map;

    }
    private int getnumberofdaysinmonth(int i) {
    return daysofmonth[i];
    }
    private String getmonthasstring(int i) {
    return months[i];
    }
    public int getCount() {

    return list.size();
    }
    public Object getItem(int position) {
    return list.get(position);
    }
    public long getItemId(int position) {
    return position;
    }
    public View getView(int position, View convertView, ViewGroup parent) {
    View row = convertView;
    if(row==null)
    {
    LayoutInflater inflater = (LayoutInflater) _context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    row = inflater.inflate(R.layout.daygrid, parent, false);
    }

    gridcell= (Button) findViewById(R.id.daygridcell);

    String[] day_color = list.get(position).split(“-“);
    String theday = day_color[0];
    String themonth = day_color[2];
    String theyear = day_color[3];
    if ((!eventsPerMonthMap.isEmpty()) && (eventsPerMonthMap != null))
    {
    if (eventsPerMonthMap.containsKey(theday))
    {
    num_events_per_day = (TextView) row.findViewById(R.id.gridviewcell);
    Integer numEvents = (Integer) eventsPerMonthMap.get(theday);
    num_events_per_day.setText(numEvents.toString());
    }
    }
    gridcell.setText(theday);
    gridcell.setTag(theday + “-” + themonth + “-” + theyear);

    if (day_color[1].equals(“GREY”))
    {
    gridcell.setTextColor(Color.LTGRAY);
    }
    if (day_color[1].equals(“WHITE”))
    {
    gridcell.setTextColor(Color.WHITE);
    }
    if (day_color[1].equals(“BLUE”))
    {
    gridcell.setTextColor(getResources().getColor(R.color.static_text_color));
    }
    return row;
    }

    }

    }

    • Hi hkr,

      Can you send me a stack trace of the error – this can be more helpful.
      I saw your comments – when I started this blog – i was in a much worse situation thatn you.
      I had no examples to learn from. So having some is alot more helpful than None.
      It is a good idea to learn to “read” code – this way you can run the logic in your mind
      and is really great for solving problems.

      -w

  48. Hello,
    Thank you for a wonderful calendar view.
    However, I have a little problem with the display of the current day.
    The number color will be changed when i choose the number ,but i don’t know how to
    change back the color .
    Plz Help Me

  49. I really appreciate this tutorial.I got a great help from this code.Can you tell me how to change the background color of all the dates which fall on sunday..I mean, I want to change the background color to RED for the 1st column of the gridview..How to achieve it please paste the source code according to the above calender source code :)

    Thanks

    Raam

  50. hi….
    i am new carrier maker of android apps…

    i wanna brief description of fundamentals of android programming…..

    how to copy and paste the proper resources…

    xml and main.java file details…

    i except on your response….

    kindly help me….

    dhinesh

    dhinesh.ag@gmail.com

  51. Hi all,
    I found another bug. Today is August 31-2012. If I click previous button twice, it should be June. Yes the date data in Gridview is show for June but the currentMonth label on top says July. It’s same if I’m August month view, I click next button one. It should be September, but no the currentMonth label on top says October.

    + The problem is because of this line:
    “_calendar.set(year, month – 1, _calendar.get(Calendar.DAY_OF_MONTH));”

    + Solve this problem by replace “_calendar.getTime()” with 15;

    + Explanation: Today is August 31-2012, If I click previous button first time, _calendar is set to year: 2012, month: July, date: 31. This is a correct date for JULY, but when I click one more time, _calendar is set to year: 2012, month: June, date: 31. This is not a true, because June only has 30 days then the 31st will be fall in JULY which is JULY 1st. THUS, for safety I would pick 15 for date for every month. Hope this quick fix won’t cause any problem.

  52. Pingback: ViewPager in custom calendar | Jisku.com - Developers Network

  53. Pingback: Implementing ViewPager in custom calendar | Jisku.com - Developers Network

  54. Pingback: Custom calendar should fill screen - feed99

  55. Hello! Thank you for posting this! :) I have serious problems getting this to run on any AVD though. It absolutely refuses all Android AVDs and keeps asking for a Google api. I’m not sure what went wrong, it’s not useful to me if I can get it to run on Android. Help, please?

  56. Hey w2davids,
    Your calendar shows the current day with dark color for all of the months. For example today is 2nd of October but the calendar shows all of the 2nd days of the months with dark color.
    Here If you guys change this If-Else Statement with the code above it only shows the current month as dark color in the Calendar View.

    Here it’s;

    if (day_color[1].equals(“GREY”)) {
    gridcell.setTextColor(Color.LTGRAY);
    }
    if (day_color[1].equals(“WHITE”)) {
    gridcell.setTextColor(Color.WHITE);
    }
    if (day_color[1].equals(“BLUE”)) {
    Calendar cal = Calendar.getInstance();

    if((cal.get(Calendar.MONTH)+1) == month) {
    // Which means today. gridcell.setTextColor(getResources().getColor(R.color.static_text_color));
    }
    }

  57. Thanks for the help, could please e-mail me code with calendar events? i need to show a day view with this calendar and i am not able to find any open source code for that.

  58. Pingback: Implementing ViewPager in custom calendar - feed99

  59. Hi,
    you are not considering condition of leap year too.
    This array selection should be dynamic.
    private final int[] daysOfMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30,
    31, 30, 31 };

    where do I make changes?

    • make this changes for leap year
      private int getNumberOfDaysOfMonth(int i) {

      if (i == 1) {

      GregorianCalendar cal = new GregorianCalendar();
      if (cal.isLeapYear(year)) {
      return 29;
      } else
      return daysOfMonth[i];
      }

      return daysOfMonth[i];
      }

  60. I want to know the code about the calender application which add the reminder, anniversary, birthday, and etc..
    so can you send the code or source of this application?
    Notify

  61. Pingback: Android Timepicker : Android Community - For Application Development

  62. Pingback: making a custom calendar like layout programicaly : Android Community - For Application Development

  63. Pingback: making a custom calendar like layout programicaly : Unlimitedtricks Programming Blog, Tutorials, jQuery, Ajax, PHP, MySQL and Demos

  64. I am trying to modify the calendar, what I would like it to do is have different colors for 7 days in a row then another color for the next 7 days then repeat itself. So for instance starting January 3 thru January 9, I want them days to be blue then from January 10 thru January 16 them days to be red. I would like this to keep going but I can not get it figured out. Any help would be greatly appreciated. I am new to creating android apps but am familiar with java.

    • I will most likely release all my code showing how to do persistence ie. storing events linked to the calendar. It was a project that needs approval before I can release my code…but dont think it would be a prob :)

      -w

  65. hi thanks for your code but i got an error in the following line
    gridcell.setTextColor(getResources().getColor(R.color.static_text_color));
    could u help me to over come.

  66. Hey I’ve used this UI for my project but the problem is that the calendar grid does not appear for some reason. Please help!
    P.S This was really helpful for my learning and can you please send me the sqlLite code to me please? Thank You :)

  67. Hello,

    I am new for your blog,

    Can you suggest me how can i add particular holidays in your code ??

    And please give me file which i can import directly for your calender app.

    Thanks

  68. This is really helpful article. However I could not download this code. Execute this code should have proper images and @drawable items. Really appreciate if you can send this code to following email address. chamendra@gmail.com

  69. Pingback: How to create events in calender Android - How-To Video

  70. thank you very much for this example so useful, I’m still trying unsuccessfully to leave several days marked an existing event, please if you could give me an idea how to make it faster you appreciate it, my mail is davidpuchoc08@gmail.com

  71. Pingback: how to change view of date picker and display like calender in datepicker in android? : Android Community - For Application Development

  72. Dear,
    i am working on my first android app because i’m going to apply as android developer this week.

    I want to implement your calender with the add events functionality.

    Can you send me the zip file with the database implementation and the add events implementation? You can send it to jonas.aarts@gmail.com.

    Thanks and in advance and good luck with your blog!

    Greetings,

    Jonas

  73. Hi,
    I have been searching for ages to find a calendar to use inside of my app, its a real pain that there is no native calendar on android we are able to call, I am aware of caledarView but this lacks any events display. I’m sure that your code would really help.
    Would you send me the zip of the calendar and any of the adding events implementation using sqlite.

    Thank you

    jacen.cartwright@gmail.com

  74. Hello ive find that calendar does not looks good on small screen devices (under 4 inch).
    Is there a way to make it feet to this screens?
    Thank you.

  75. i am totally new to this, i wish to create a simple calender widget for my android phone, may i know what software you use ?

  76. Pingback: Custom calendar dayview in android | BlogoSfera

  77. Pingback: Binary App Dev: Apps | Adding events to my own calender in Android

  78. Dear w2davids. Thanks for the wonderful creation. I realize that it is impossible to you to check all the comments written here during almost 3 years. But if you search rapidly you can find at least 20 comments, requesting for the code that enables us to add events in your calendar. I also request you for the same. Please post the code snippet for adding day by day events. If you can please send me the code snippet to webgrity49@gmail.com

    • Dear Eclipse-fan,
      You made me laugh :). When I started this blog, I thought..mmh if only 10 people look at it…mmh ok!…Call it a day and off to the coffee shop. I was unemployed….LOL what a combination. You know that’s life.

      But as you mentioned 3 yrs later…its still up! And its only a small part of the work that I have done on Android…

      I would like to make the code available, but some of these projects were done for clients and therefore need approval. I have taken the solution that I have applied, but removed the context and simplified it
      so others can learn and benefit from it and even expand upon my solutions.

      Well…mmh I have an idea..check this blog later!

  79. I see that the parsed date is filled with unnecessary things (for me).
    Basically I only need 3 things:
    – The date’s day (e.g. 17, 19, 25 etc..)
    – The date’s month (e.g. August, October, January etc..)
    – The date’s year (e.g. 2013, 2022, 2050 etc..)

    I want to use each data separately, for example:
    if (day == 17 && month==August)
    {
    Toast.makeText(this, “This is my Birthday!”, Toast.LENGTH_SHORT).show();
    }

    How do I retrieve it this way?

    Thank you,
    Omga4000.

  80. Hello thanks in advanced for your time and work !!

    I’ve a doubt

    private final int[] daysOfMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    What happens if February has 29 days ?

    Thanks !!

  81. Brilliant looking calendar but has anybody successfully implemented adding an event into a SQLite database (or other method) and be willing to share their code?

    Thanks

  82. any one help me please …

    I tried to customize this calender as “Whenever Date is selected from the calendar, the selected date is marked with symbol. Since we used the onclick listener for the entire calendar the marked symbol in selected date can’t able to hide when another date is selected. It remains selected until we move to another activity or refreshing the particular activity.” ..

    How to mark the selected date with symbol or color and if another date is selected i need to remove the symbol from the previous date and want to mark for selected date.??

  83. hi there,
    can some one help me? i get this when i tried to run the project
    11-13 23:50:29.427: D/dalvikvm(533): GC_CONCURRENT freed 1K, 4% free 10407K/10759K, paused 4ms+3ms
    11-13 23:50:29.517: D/dalvikvm(533): GC_FOR_ALLOC freed 3K, 2% free 10623K/10759K, paused 32ms
    11-13 23:50:29.557: D/AndroidRuntime(533): Shutting down VM
    11-13 23:50:29.557: W/dalvikvm(533): threadid=1: thread exiting with uncaught exception (group=0x409961f8)
    11-13 23:50:29.567: E/AndroidRuntime(533): FATAL EXCEPTION: main
    11-13 23:50:29.567: E/AndroidRuntime(533): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.examples/com.examples.Main}: java.lang.ClassCastException: android.widget.ImageView cannot be cast to android.widget.Button
    11-13 23:50:29.567: E/AndroidRuntime(533): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1955)
    11-13 23:50:29.567: E/AndroidRuntime(533): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1980)
    11-13 23:50:29.567: E/AndroidRuntime(533): at android.app.ActivityThread.access$600(ActivityThread.java:122)
    11-13 23:50:29.567: E/AndroidRuntime(533): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1146)
    11-13 23:50:29.567: E/AndroidRuntime(533): at android.os.Handler.dispatchMessage(Handler.java:99)
    11-13 23:50:29.567: E/AndroidRuntime(533): at android.os.Looper.loop(Looper.java:137)
    11-13 23:50:29.567: E/AndroidRuntime(533): at android.app.ActivityThread.main(ActivityThread.java:4340)
    11-13 23:50:29.567: E/AndroidRuntime(533): at java.lang.reflect.Method.invokeNative(Native Method)
    11-13 23:50:29.567: E/AndroidRuntime(533): at java.lang.reflect.Method.invoke(Method.java:511)
    11-13 23:50:29.567: E/AndroidRuntime(533): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    11-13 23:50:29.567: E/AndroidRuntime(533): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    11-13 23:50:29.567: E/AndroidRuntime(533): at dalvik.system.NativeStart.main(Native Method)
    11-13 23:50:29.567: E/AndroidRuntime(533): Caused by: java.lang.ClassCastException: android.widget.ImageView cannot be cast to android.widget.Button
    11-13 23:50:29.567: E/AndroidRuntime(533): at com.examples.Main.onCreate(Main.java:64)
    11-13 23:50:29.567: E/AndroidRuntime(533): at android.app.Activity.performCreate(Activity.java:4465)
    11-13 23:50:29.567: E/AndroidRuntime(533): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
    11-13 23:50:29.567: E/AndroidRuntime(533): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1919)
    11-13 23:50:29.567: E/AndroidRuntime(533): … 11 more

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s