Creating Custom Calendar with Android Studio
Getting Started
Create a new Empty MainActivity project in Android Studio with xml layout activity_main.xml.
To create a layout as shown in the image above, we will create a need layout resource file in res > layout named simple_calendar.xml.
For calendar layout, we need LinearLayout inside which using TextViews and other nested LinearLayout we will create the calendar. Here is the XML code of the same.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:orientation="vertical"> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal"> <TextView
android:id="@+id/current_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/green"
android:textSize="28sp" /> <TextView
android:id="@+id/current_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:textColor="@color/green"
android:textSize="28sp" /> </LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="7"> <Button
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:text="S"
android:textColor="@color/green"
android:textSize="16sp" /> <Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:text="S"
android:textColor="@color/green"
android:textSize="16sp" /> <Button
android:id="@+id/button10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:text="M"
android:textColor="@color/green"
android:textSize="16sp" /> <Button
android:id="@+id/button9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:text="T"
android:textColor="@color/green"
android:textSize="16sp" /> <Button
android:id="@+id/button8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:text="W"
android:textColor="@color/green"
android:textSize="16sp" /> <Button
android:id="@+id/button7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:text="T"
android:textColor="@color/green"
android:textSize="16sp" /> <Button
android:id="@+id/button6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:text="F"
android:textColor="@color/green"
android:textSize="16sp" /> </LinearLayout> <LinearLayout
android:id="@+id/calendar_week_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="7" /> <LinearLayout
android:id="@+id/calendar_week_2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="7" /> <LinearLayout
android:id="@+id/calendar_week_3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="7" /> <LinearLayout
android:id="@+id/calendar_week_4"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="7" /> <LinearLayout
android:id="@+id/calendar_week_5"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="7" /> <LinearLayout
android:id="@+id/calendar_week_6"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="7" /></LinearLayout>
Now create a java file named SimpleCalendar.java which extends LinearLayout. Here is the code for the same:
package com.example.customcalendar;import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.Calendar;
public class SimpleCalendar extends LinearLayout {
private static final String CUSTOM_GREY = "#a0a0a0";
private static final String[] ENG_MONTH_NAMES = {"January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December"}; private Button selectedDayButton;
private Button[] days;
LinearLayout weekOneLayout;
LinearLayout weekTwoLayout;
LinearLayout weekThreeLayout;
LinearLayout weekFourLayout;
LinearLayout weekFiveLayout;
LinearLayout weekSixLayout;
private LinearLayout[] weeks; private int currentDateDay, chosenDateDay, currentDateMonth,
chosenDateMonth, currentDateYear, chosenDateYear,
pickedDateDay, pickedDateMonth, pickedDateYear;
int userMonth, userYear;
private DayClickListener mListener; private Calendar calendar;
LinearLayout.LayoutParams defaultButtonParams;
private LinearLayout.LayoutParams userButtonParams; public SimpleCalendar(Context context) {
super(context);
init(context);
} public SimpleCalendar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
} public SimpleCalendar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public SimpleCalendar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context);
} @SuppressLint("SetTextI18n")
private void init(Context context) {
DisplayMetrics metrics = getResources().getDisplayMetrics(); View view = LayoutInflater.from(context).inflate(R.layout.simple_calendar, this, true);
calendar = Calendar.getInstance(); weekOneLayout = view.findViewById(R.id.calendar_week_1);
weekTwoLayout = view.findViewById(R.id.calendar_week_2);
weekThreeLayout = view.findViewById(R.id.calendar_week_3);
weekFourLayout = view.findViewById(R.id.calendar_week_4);
weekFiveLayout = view.findViewById(R.id.calendar_week_5);
weekSixLayout = view.findViewById(R.id.calendar_week_6);
TextView currentDate = view.findViewById(R.id.current_date);
TextView currentMonth = view.findViewById(R.id.current_month); currentDateDay = chosenDateDay = calendar.get(Calendar.DAY_OF_MONTH); if (userMonth != 0 && userYear != 0) {
currentDateMonth = chosenDateMonth = userMonth;
currentDateYear = chosenDateYear = userYear;
} else {
currentDateMonth = chosenDateMonth = calendar.get(Calendar.MONTH);
currentDateYear = chosenDateYear = calendar.get(Calendar.YEAR);
} currentDate.setText("" + currentDateDay);
currentMonth.setText(ENG_MONTH_NAMES[currentDateMonth]); initializeDaysWeeks();
if (userButtonParams != null) {
defaultButtonParams = userButtonParams;
} else {
defaultButtonParams = getdaysLayoutParams();
}
addDaysinCalendar(defaultButtonParams, context, metrics); initCalendarWithDate(chosenDateYear, chosenDateMonth, chosenDateDay); } private void initializeDaysWeeks() {
weeks = new LinearLayout[6];
days = new Button[6 * 7]; weeks[0] = weekOneLayout;
weeks[1] = weekTwoLayout;
weeks[2] = weekThreeLayout;
weeks[3] = weekFourLayout;
weeks[4] = weekFiveLayout;
weeks[5] = weekSixLayout;
} private void initCalendarWithDate(int year, int month, int day) {
if (calendar == null)
calendar = Calendar.getInstance();
calendar.set(year, month, day); int daysInCurrentMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); chosenDateYear = year;
chosenDateMonth = month;
chosenDateDay = day; calendar.set(year, month, 1);
int firstDayOfCurrentMonth = calendar.get(Calendar.DAY_OF_WEEK); calendar.set(year, month, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); int dayNumber = 1;
int daysLeftInFirstWeek;
int indexOfDayAfterLastDayOfMonth; if (firstDayOfCurrentMonth != 1) {
daysLeftInFirstWeek = firstDayOfCurrentMonth;
indexOfDayAfterLastDayOfMonth = daysLeftInFirstWeek + daysInCurrentMonth;
for (int i = firstDayOfCurrentMonth; i < firstDayOfCurrentMonth + daysInCurrentMonth; ++i) {
if (currentDateMonth == chosenDateMonth
&& currentDateYear == chosenDateYear
&& dayNumber == currentDateDay) {
days[i].setBackgroundColor(getResources().getColor(R.color.pink));
days[i].setTextColor(Color.WHITE);
} else {
days[i].setTextColor(Color.BLACK);
days[i].setBackgroundColor(Color.TRANSPARENT);
} int[] dateArr = new int[3];
dateArr[0] = dayNumber;
dateArr[1] = chosenDateMonth;
dateArr[2] = chosenDateYear;
days[i].setTag(dateArr);
days[i].setText(String.valueOf(dayNumber)); days[i].setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onDayClick(v);
}
});
++dayNumber;
}
} else {
daysLeftInFirstWeek = 8;
indexOfDayAfterLastDayOfMonth = daysLeftInFirstWeek + daysInCurrentMonth;
for (int i = 8; i < 8 + daysInCurrentMonth; ++i) {
if (currentDateMonth == chosenDateMonth
&& currentDateYear == chosenDateYear
&& dayNumber == currentDateDay) {
days[i].setBackgroundColor(getResources().getColor(R.color.pink));
days[i].setTextColor(Color.WHITE);
} else {
days[i].setTextColor(Color.BLACK);
days[i].setBackgroundColor(Color.TRANSPARENT);
} int[] dateArr = new int[3];
dateArr[0] = dayNumber;
dateArr[1] = chosenDateMonth;
dateArr[2] = chosenDateYear;
days[i].setTag(dateArr);
days[i].setText(String.valueOf(dayNumber)); days[i].setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onDayClick(v);
}
});
++dayNumber;
}
} if (month > 0)
calendar.set(year, month - 1, 1);
else
calendar.set(year - 1, 11, 1);
int daysInPreviousMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH); for (int i = daysLeftInFirstWeek - 1; i >= 0; --i) {
int[] dateArr = new int[3]; if (chosenDateMonth > 0) {
if (currentDateMonth != chosenDateMonth - 1
|| currentDateYear != chosenDateYear
|| daysInPreviousMonth != currentDateDay) {
days[i].setBackgroundColor(Color.TRANSPARENT);
} dateArr[0] = daysInPreviousMonth;
dateArr[1] = chosenDateMonth - 1;
dateArr[2] = chosenDateYear;
} else {
if (currentDateMonth != 11
|| currentDateYear != chosenDateYear - 1
|| daysInPreviousMonth != currentDateDay) {
days[i].setBackgroundColor(Color.TRANSPARENT);
} dateArr[0] = daysInPreviousMonth;
dateArr[1] = 11;
dateArr[2] = chosenDateYear - 1;
} days[i].setTag(dateArr);
days[i].setText(String.valueOf(daysInPreviousMonth--));
days[i].setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onDayClick(v);
}
});
} int nextMonthDaysCounter = 1;
for (int i = indexOfDayAfterLastDayOfMonth; i < days.length; ++i) {
int[] dateArr = new int[3]; if (chosenDateMonth < 11) {
if (currentDateMonth == chosenDateMonth + 1
&& currentDateYear == chosenDateYear
&& nextMonthDaysCounter == currentDateDay) {
days[i].setBackgroundColor(getResources().getColor(R.color.pink));
} else {
days[i].setBackgroundColor(Color.TRANSPARENT);
} dateArr[0] = nextMonthDaysCounter;
dateArr[1] = chosenDateMonth + 1;
dateArr[2] = chosenDateYear;
} else {
if (currentDateMonth == 0
&& currentDateYear == chosenDateYear + 1
&& nextMonthDaysCounter == currentDateDay) {
days[i].setBackgroundColor(getResources().getColor(R.color.pink));
} else {
days[i].setBackgroundColor(Color.TRANSPARENT);
} dateArr[0] = nextMonthDaysCounter;
dateArr[1] = 0;
dateArr[2] = chosenDateYear + 1;
} days[i].setTag(dateArr);
days[i].setTextColor(Color.parseColor(CUSTOM_GREY));
days[i].setText(String.valueOf(nextMonthDaysCounter++));
days[i].setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onDayClick(v);
}
});
} calendar.set(chosenDateYear, chosenDateMonth, chosenDateDay);
} public void onDayClick(View view) {
mListener.onDayClick(view); if (selectedDayButton != null) {
if (chosenDateYear == currentDateYear
&& chosenDateMonth == currentDateMonth
&& pickedDateDay == currentDateDay) {
selectedDayButton.setBackgroundColor(getResources().getColor(R.color.pink));
selectedDayButton.setTextColor(Color.WHITE);
} else {
selectedDayButton.setBackgroundColor(Color.TRANSPARENT);
if (selectedDayButton.getCurrentTextColor() != Color.RED) {
selectedDayButton.setTextColor(getResources()
.getColor(R.color.calendar_number));
}
}
} selectedDayButton = (Button) view;
if (selectedDayButton.getTag() != null) {
int[] dateArray = (int[]) selectedDayButton.getTag();
pickedDateDay = dateArray[0];
pickedDateMonth = dateArray[1];
pickedDateYear = dateArray[2];
} if (pickedDateYear == currentDateYear
&& pickedDateMonth == currentDateMonth
&& pickedDateDay == currentDateDay) {
selectedDayButton.setBackgroundColor(getResources().getColor(R.color.pink));
selectedDayButton.setTextColor(Color.WHITE);
} else {
selectedDayButton.setBackgroundColor(getResources().getColor(R.color.grey));
if (selectedDayButton.getCurrentTextColor() != Color.RED) {
selectedDayButton.setTextColor(Color.WHITE);
}
}
} private void addDaysinCalendar(LayoutParams buttonParams, Context context,
DisplayMetrics metrics) {
int engDaysArrayCounter = 0; for (int weekNumber = 0; weekNumber < 6; ++weekNumber) {
for (int dayInWeek = 0; dayInWeek < 7; ++dayInWeek) {
final Button day = new Button(context);
day.setTextColor(Color.parseColor(CUSTOM_GREY));
day.setBackgroundColor(Color.TRANSPARENT);
day.setLayoutParams(buttonParams);
day.setTextSize((int) metrics.density * 8);
day.setSingleLine(); days[engDaysArrayCounter] = day;
weeks[weekNumber].addView(day); ++engDaysArrayCounter;
}
}
} private LayoutParams getdaysLayoutParams() {
LinearLayout.LayoutParams buttonParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
buttonParams.weight = 1;
return buttonParams;
} public void setUserDaysLayoutParams(LinearLayout.LayoutParams userButtonParams) {
this.userButtonParams = userButtonParams;
} public void setUserCurrentMonthYear(int userMonth, int userYear) {
this.userMonth = userMonth;
this.userYear = userYear;
} public void setDayBackground(Drawable userDrawable) {
Drawable userDrawable1 = userDrawable;
} public interface DayClickListener {
void onDayClick(View view);
} public void setCallBack(DayClickListener mListener) {
this.mListener = mListener;
}}
Now in activity_main.xml you can easily create a SimpleCalendar widget. Set its height and width as they are the required attributes. Here is the code for the same.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="horizontal"> <com.example.customcalendar.SimpleCalendar
android:id="@+id/square_day"
android:layout_width="match_parent"
android:layout_height="wrap_content"/></LinearLayout>
Now in MainActivity.java, create SimpleCalendar object and using findViewByID link it with the XML widget . Here is the code for the same:
package com.example.customcalendar;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;import java.util.Calendar;public class MainActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); SimpleCalendar simpleCalendar = findViewById(R.id.square_day);
Calendar calendar = Calendar.getInstance();
// Get current month
int month = calendar.get(Calendar.MONTH); //Get current Year
int year = calendar.get(Calendar.YEAR); simpleCalendar.setUserCurrentMonthYear(month,year);
simpleCalendar.setCallBack(new SimpleCalendar.DayClickListener() {
@Override
public void onDayClick(View view) {
// Create on Click event here.
}
});
}}