Calendar control we should be familiar with, github above a lot of search, but we got a github calendar control, want to start to change the function and change the requirements, sometimes may feel confused, (of course, the old driver ignored me -. So, if you want to know how a calendar control was built from scratch, take a quick look at this article. The main article is to take you step by step familiar with the construction process, and there is no particularly cool crazy drag effect.

First on a rendering of the town building.

I. Data preparation

1, entity class MyCalendarBean

/** * Created by deeson.woo */ public class MyCalendarBean { private int year; private int month; //1-12 private int day; //1-31 public MyCalendarBean(int year, int month, int day) { this.year = year; this.month = month; this.day = day; } public intgetYear() {
        return year;
    }

    public int getMonth() {
        return month;
    }

    public int getDay() {
        returnday; }}Copy the code

2. Build the date entity

/** * Build a day object * @param year * @param month * @param day * @return
     */
    public MyCalendarBean generateCalendarBean(int year, int month, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, day);
        year = calendar.get(Calendar.YEAR);
        month = calendar.get(Calendar.MONTH) + 1;
        day = calendar.get(Calendar.DATE);

        return new MyCalendarBean(year, month, day);
    }
Copy the code

3. Print all dates for the current month

/** * Get the list of dates for the current month * @param year * @param month * @return
     */
    public List<MyCalendarBean> getDaysListOfMonth(int year, int month) {

        List<MyCalendarBean> list = new ArrayList<>();

        int daysOfMonth = getDaysOfCertainMonth(year, month);

        for (int i = 0; i < daysOfMonth; i++) {
            MyCalendarBean bean = generateCalendarBean(year, month, i + 1);
            list.add(bean);
        }
        returnlist; } /** * Obtain the maximum number of days in a specific month ** @param year * @param month * @return
     */
    public static int getDaysOfCertainMonth(int year, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, 1);
        return calendar.getActualMaximum(Calendar.DATE);
    }
Copy the code
// Test print February 2018printDaysList(getDaysListOfMonth(2018, 2));
Copy the code

In February 2018 =,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28 {1}

Ii. Date of presentation

1. Show all the dates of the month in seven columns

Custom ViewGroup (MonthCalendarView)

/** * Created by deeson. Woo */ public class MonthCalendarView extends ViewGroup {private int column = 7; public MonthCalendarView(Context context) { super(context); } public MonthCalendarView(Context context, AttributeSet attrs) { super(context, attrs); }}Copy the code
(1) onMeasure () method
  • Take the width of the control, divide it into seven parts, and assign the width and height of the item
  • The height required for the control is also calculated
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int parentWidth = MeasureSpec.getSize(MeasureSpec.makeMeasureSpec(widthMeasureSpec, MeasureSpec.EXACTLY)); Int itemWidth = parentWidth/column; int itemWidth = parentWidth/column; int itemHeight = itemWidth; int parentHeight = 0;for(int i = 0; i < getChildCount(); i++) { View childView = getChildAt(i); childView.measure(MeasureSpec.makeMeasureSpec(itemWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(itemHeight, MeasureSpec.EXACTLY)); // Calculate the height required for the controlif(i % column == 0) { parentHeight += childView.getMeasuredHeight(); }}setMeasuredDimension(parentWidth, parentHeight);
    }
Copy the code
(2) onLayout () method
  • Calculate the left, top, right, and bottom values of each item in a seven-column layout and add them precisely to the control
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        for(int i = 0; i < getChildCount(); i++) { View itemView = getChildAt(i); int columnCount = i % column; int rowCount = i / column; int itemWidth = itemView.getMeasuredWidth(); int itemHeight = itemView.getMeasuredHeight(); left = columnCount * itemWidth; top = rowCount * itemHeight; right = left + itemWidth; bottom = top + itemHeight; itemView.layout(left, top, right, bottom); }}Copy the code
(3) Fill in the month and date data
  • Expose a public method to populate the data
  • Build a list of dates based on the year and month passed in
  • Build itemViews one by one and populate them in the control
  • Call the requestLayout () method to redraw
    public void setMonth(int year, int month) {
        mList = calendarUtils.getDaysListOfMonth(year, month);
        addAllItem();
        requestLayout();
    }

    private void addAllItem() {
        for (int i = 0; i < mList.size(); i++) {
            MyCalendarBean bean = mList.get(i);

            View itemView = generateDateView(bean);
            addViewInLayout(itemView, i, itemView.getLayoutParams(), true);
        }
    }

    private View generateDateView(MyCalendarBean bean) {
        View itemView = LayoutInflater.from(getContext()).inflate(R.layout.item_date_view, null);
        if (bean.isCurrentMonth()) {
            TextView date = itemView.findViewById(R.id.date);
            date.setText(String.valueOf(bean.getDay()));
        }
        return itemView;
    }
Copy the code

Put the item_date_view. XML layout out as well

<? xml version="1.0" encoding="utf-8"? > <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/date"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:textSize="14sp"
        android:textColor="@color/text_black"
        />

</RelativeLayout>
Copy the code

2. Use it in layouts

<? 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="match_parent"
    android:orientation="vertical"
    android:background="@color/background_white"
    >

    <com.example.deesonwoo.mysimplecalendar.calendar.MonthCalendarView
        android:id="@+id/month_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent">

    </com.example.deesonwoo.mysimplecalendar.calendar.MonthCalendarView>

</LinearLayout>

Copy the code

3. Use in MainActivity

package com.example.deesonwoo.mysimplecalendar;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.example.deesonwoo.mysimplecalendar.calendar.MonthCalendarView;
import com.example.deesonwoo.mysimplecalendar.calendar.MyCalendarBean;
import com.example.deesonwoo.mysimplecalendar.calendar.MyCalendarUtils;

import java.util.List;

public class MainActivity extends AppCompatActivity {

    MonthCalendarView monthView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        monthView = findViewById(R.id.month_view);
        initCalendar();
    }

    private void initCalendar() {// test display monthview.setMonth (2018, 3); }}Copy the code

The effect is shown as follows:

4. Add the top weekly layout

<? 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="match_parent"
    android:orientation="vertical"
    android:background="@color/background_white"
    >


    <LinearLayout
        android:id="@+id/week_layout"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:orientation="horizontal"
        android:background="@color/white"
        >

        <TextView
            android:id="@+id/week_00"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:text="Sunday"
            android:textColor="@color/text_black"
            android:textSize="12sp" />

        <TextView
            android:id="@+id/week_01"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:text="On Monday"
            android:textColor="@color/text_black"
            android:textSize="12sp" />

        <TextView
            android:id="@+id/week_02"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:text="Tuesday"
            android:textColor="@color/text_black"
            android:textSize="12sp" />

        <TextView
            android:id="@+id/week_03"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:text="On Wednesday"
            android:textColor="@color/text_black"
            android:textSize="12sp" />

        <TextView
            android:id="@+id/week_04"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:text="Thursday"
            android:textColor="@color/text_black"
            android:textSize="12sp" />

        <TextView
            android:id="@+id/week_05"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:text="Friday"
            android:textColor="@color/text_black"
            android:textSize="12sp" />

        <TextView
            android:id="@+id/week_06"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:gravity="center"
            android:text="Saturday"
            android:textColor="@color/text_black"
            android:textSize="12sp" />
    </LinearLayout>

    <com.example.deesonwoo.mysimplecalendar.calendar.MonthCalendarView
        android:id="@+id/month_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent">

    </com.example.deesonwoo.mysimplecalendar.calendar.MonthCalendarView>

</LinearLayout>

Copy the code

The effect is as follows:

5. Optimize the mapping between the date and the week

I’m sure you’ve noticed that in the effect shown above, there is no one-to-one arrangement of days and days. Next, let’s optimize.

  • Finds the week corresponding to the first day of the current month
  • Modify the utility class method getDaysListOfMonth () to populate the month list with the dates of the previous month that were previously vacant
  • Hide the date of last month
Add the following method to the MyCalendarUtils utility class
** @param year * @param month * @param day * @return1-7(Sunday-Saturday) */ private int weekdayoncertainDate (int Year, int month, int day) { Calendar calendar = Calendar.getInstance(); calendar.set(year, month - 1, day);return calendar.get(Calendar.DAY_OF_WEEK);
    }
Copy the code
(2) Modify the getDaysListOfMonth () method to fill the month list with the previous month
/** * Get the list of dates for the current month ** @param year * @param month * @return*/ public List<MyCalendarBean> getDaysListOfMonth(int year, int month) { List<MyCalendarBean> list = new ArrayList<>(); int daysOfMonth = getDaysOfCertainMonth(year, month); Int weekDayOfFirstDay = getWeekDayOnCertainDate(year, month, 1); // GetWeekdayOffirstDay = getWeekDayOnCertainDate(year, month, 1); int preMonthDays = weekDayOfFirstDay - 1;for (int i = preMonthDays; i > 0; i--) {
            MyCalendarBean preMonthBean = generateCalendarBean(year, month, 1 - i);
            list.add(preMonthBean);
        }

        for (int i = 0; i < daysOfMonth; i++) {
            MyCalendarBean monthBean = generateCalendarBean(year, month, i + 1);
            list.add(monthBean);
        }
        return list;
    }
Copy the code

The display effect is as follows:

Obviously, the date of the last month needs to be displayed or hidden here, otherwise it will cause visual trouble to the user. Here, I will directly do the hidden operation.

(3) Add the current month identifier, isCurrentMonth, to the date entity class, and assign a value to the identifier when building the data.

The entity classes are as follows:

/** * Created by deeson.woo */ public class MyCalendarBean { private int year; private int month; //1-12 private int day; //1-31 private boolean isCurrentMonth =true; Public MyCalendarBean(int year, int month, int day) {this.year = year; this.month = month; this.day = day; } public intgetYear() {
        return year;
    }

    public int getMonth() {
        return month;
    }

    public int getDay() {
        return day;
    }

    public boolean isCurrentMonth() {
        return isCurrentMonth;
    }

    public void setCurrentMonth(boolean currentMonth) { isCurrentMonth = currentMonth; }}Copy the code

To assign a value to the id, assign a value to getDaysListOfMonth () :

/** * Get the list of dates for the current month ** @param year * @param month * @return*/ public List<MyCalendarBean> getDaysListOfMonth(int year, int month) { List<MyCalendarBean> list = new ArrayList<>(); int daysOfMonth = getDaysOfCertainMonth(year, month); Int weekDayOfFirstDay = getWeekDayOnCertainDate(year, month, 1); // GetWeekdayOffirstDay = getWeekDayOnCertainDate(year, month, 1); int preMonthDays = weekDayOfFirstDay - 1;for (int i = preMonthDays; i > 0; i--) {
            MyCalendarBean preMonthBean = generateCalendarBean(year, month, 1 - i);
            preMonthBean.setCurrentMonth(false);
            list.add(preMonthBean);
        }

        for (int i = 0; i < daysOfMonth; i++) {
            MyCalendarBean monthBean = generateCalendarBean(year, month, i + 1);
            monthBean.setCurrentMonth(true);
            list.add(monthBean);
        }
        return list;
    }
Copy the code

Finally modify the generateDateView () method in our custom calendar class to not show the date of the last month:

    private View generateDateView(MyCalendarBean bean) {
        View itemView = LayoutInflater.from(getContext()).inflate(R.layout.item_date_view, null);
        if(bean.isCurrentMonth()){
            TextView date = itemView.findViewById(R.id.date);
            date.setText(String.valueOf(bean.getDay()));
        }
        return itemView;
    }
Copy the code

The effect is as follows:

3. Continuous optimization and improvement

1. Change the static calendar to dynamic toggle display

(1) Add a header layout for displaying the current month and turning pages
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/background_blue"
        >
        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:textSize="20sp"
            android:textColor="@color/white"
            />

        <ImageView
            android:id="@+id/pre_month"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_centerVertical="true"
            android:layout_alignParentLeft="true"
            android:src="@mipmap/btn_preview"
            />
        <ImageView
            android:id="@+id/next_month"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_centerVertical="true"
            android:layout_alignParentRight="true"
            android:src="@mipmap/btn_next"
            />

    </RelativeLayout>
Copy the code

##### (2) Modify the custom calendar class

  • Adds the currently displayed month member variable

private int mYear, mMonth;

  • Modify the construction method and the way data is populated
    public MonthCalendarView(Context context) {
        super(context);
        calendarUtils = new MyCalendarUtils(context);
    }

    public MonthCalendarView(Context context, AttributeSet attrs) {
        super(context, attrs);
        calendarUtils = new MyCalendarUtils(context);
    }

    public void setMonth(int year, int month) {
        this.mYear = year;
        this.mMonth = month;
        invalidateMonth();
    }

    private void invalidateMonth() {
        mList = calendarUtils.getDaysListOfMonth(mYear, mMonth);
        removeAllViews();
        addAllItem();
        requestLayout();
    }
Copy the code
  • Add the methods of page turning and page turning
/** * Show last month */ public voidmoveToPreMonth() { mMonth -= 1; invalidateMonth(); } /** * Show the next month */ public voidmoveToNextMonth() {
        mMonth += 1;
        invalidateMonth();
    }
Copy the code
  • Added a method to get the current display date
    public String getCurrentYearAndMonth() {
        return MyCalendarUtils.formatYearAndMonth(mYear, mMonth);
    }
Copy the code
(3) Add tool class methods
/** * Format the title to display * @param year * @param month * @return
     */
    public static String formatYearAndMonth(int year, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, 1);
        year = calendar.get(Calendar.YEAR);
        month = calendar.get(Calendar.MONTH) + 1;
        return year + "Year" + month + "Month"; } /** * Obtain the current date of the system ** @return
     */
    public static int[] getNowDayFromSystem() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        return new int[]{cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DATE)};
    }
Copy the code
(4) Modify the MainActivity class
  • Changing the theme style
  • Added header layout relevance
  • The current date of the system is displayed by default
package com.example.deesonwoo.mysimplecalendar;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;

import com.example.deesonwoo.mysimplecalendar.calendar.MonthCalendarView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    MonthCalendarView monthView;
    ImageView btnPreMonth, btnNextMonth;
    TextView title;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_main);
        monthView = findViewById(R.id.month_view);
        initCalendar();
        initTitleView();
        updateTitle();
    }

    private void initCalendar() {
        int[] nowDay = MyCalendarUtils.getNowDayFromSystem();
        monthView.setMonth(nowDay[0], nowDay[1]);
    }

    private void initTitleView() { title = findViewById(R.id.title); btnPreMonth = findViewById(R.id.pre_month); btnNextMonth = findViewById(R.id.next_month); btnPreMonth.setOnClickListener(this); btnNextMonth.setOnClickListener(this); } /** * Refresh the title to display the date */ private voidupdateTitle() {
        String yearAndMonth = monthView.getCurrentYearAndMonth();
        title.setText(yearAndMonth);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.pre_month:
                monthView.moveToPreMonth();
                updateTitle();
                break;
            case R.id.next_month:
                monthView.moveToNextMonth();
                updateTitle();
                break; }}}Copy the code

The final display is as follows:

2. Added highlight to the system date

  • Added tool class methods
/** * Check whether it is * @param bean * @return
     */
    public static boolean isToday(MyCalendarBean bean) {
        int[] nowDay = getNowDayFromSystem();
        return bean.getYear() == nowDay[0] && bean.getMonth() == nowDay[1] && bean.getDay() == nowDay[2];
    }
Copy the code
  • Method to modify the custom calendar class build date
    private View generateDateView(MyCalendarBean bean) {
        View itemView = LayoutInflater.from(getContext()).inflate(R.layout.item_date_view, null);
        if (bean.isCurrentMonth()) {
            TextView date = itemView.findViewById(R.id.date);
            if (MyCalendarUtils.isToday(bean)) {
                date.setBackgroundResource(R.drawable.item_today_bg);
            }
            date.setText(String.valueOf(bean.getDay()));
        }
        return itemView;
    }
Copy the code
  • The system highlights the background item_today_bg.xml for the day
<? xml version="1.0" encoding="utf-8"? > <shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid
        android:color="@color/theme_color" />

</shape>
Copy the code

The effect is as follows:

3. Add the click date effect

(1) Modify the custom calendar class
  • Modify the build date method
    private View generateDateView(MyCalendarBean bean) {
        View itemView = LayoutInflater.from(getContext()).inflate(R.layout.item_date_view, null);
        if (bean.isCurrentMonth()) {
            TextView date = itemView.findViewById(R.id.date);
            if (MyCalendarUtils.isToday(bean)) {
                date.setBackgroundResource(R.drawable.item_today_bg);
            } else {
                date.setBackgroundResource(R.drawable.item_pick_up);
            }
            date.setText(String.valueOf(bean.getDay()));
        }
        return itemView;
    }
Copy the code
  • item_pick_up.xml
<? xml version="1.0" encoding="utf-8"? > <selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_selected="true">
        <shape android:shape="oval">
            <stroke android:color="@color/theme_color" android:width="1dp"/>
        </shape>
    </item>

    <item android:drawable="@android:color/transparent" />
</selector>
Copy the code
  • Added the callback interface method for clicking on the home screen
    private OnDatePickUpListener onDatePickUpListener;

    public void setOnDatePickUpListener(OnDatePickUpListener onDatePickUpListener) {
        this.onDatePickUpListener = onDatePickUpListener;
    }

    public interface OnDatePickUpListener {
        void onDatePickUp(MyCalendarBean bean);
    }
Copy the code
  • Modified method of adding date to add click listen
    private void addAllItem() {
        for (int i = 0; i < mList.size(); i++) {
            final MyCalendarBean bean = mList.get(i);

            final View itemView = generateDateView(bean);
            addViewInLayout(itemView, i, itemView.getLayoutParams(), true);
            final int position = i;
            itemView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {

                    if (pickUpPosition == position) {
                        return;
                    }

                    if(pickUpPosition ! = -1) { getChildAt(pickUpPosition).setSelected(false);
                    }
                    itemView.setSelected(true);

                    if(null ! = onDatePickUpListener) { onDatePickUpListener.onOnDatePickUp(bean); } pickUpPosition = position; }}); }}Copy the code
(2) Call in MainActivity
    private void initCalendar() {
        int[] nowDay = MyCalendarUtils.getNowDayFromSystem();
        monthView.setMonth(nowDay[0], nowDay[1]);
        monthView.setOnDatePickUpListener(new MonthCalendarView.OnDatePickUpListener() { @Override public void onDatePickUp(MyCalendarBean bean) { Toast.makeText(MainActivity.this, bean.toString(), Toast.LENGTH_SHORT).show(); }}); }Copy the code

The effect is as follows:

Four, integration of custom controls

You might think that our custom controls are finished here, but young, simple, naive…… In keeping with the principle of high cohesion and low coupling, I have integrated the newly emerged operations into a single control, SimpleCalendarView. Let’s just go straight to the code, it’s only a few lines, and I don’t want to explain anything.

1, SimpleCalendarView class

  • Add the title view, week view, and calendar view to the custom SimpleCalendarView class one by one, and then add the related interfaces. See the code below
package com.example.deesonwoo.mysimplecalendar.calendar; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import com.example.deesonwoo.mysimplecalendar.R; public class SimpleCalendarView extends LinearLayout implements View.OnClickListener, MonthCalendarView.OnDatePickUpListener { private MonthCalendarView monthCalendarView; Private OnDatePickListener OnDatePickListener; private TextView title; public SimpleCalendarView(Context context) { this(context, null); } public SimpleCalendarView(Context context, AttributeSet attrs) { super(context, attrs);setOrientation(VERTICAL);
        setBackgroundColor(context.getResources().getColor(R.color.white)); TitleParams = new LayoutParams(LayoutParams.MATCH_PARENT, MyCalendarUtils. Dp2px (context, 50)); RelativeLayout titleLayout = (RelativeLayout) LayoutInflater.from(context).inflate(R.layout.title_layout, null); title = titleLayout.findViewById(R.id.title); ImageView preMonth = titleLayout.findViewById(R.id.pre_month); ImageView nextMonth = titleLayout.findViewById(R.id.next_month); preMonth.setOnClickListener(this); nextMonth.setOnClickListener(this); addView(titleLayout, titleParams); = new LayoutParams(layoutparams.match_parent, mycalendarutils.dp2px (context, 40)); LinearLayout weekLayout = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.week_layout, null); addView(weekLayout, weekParams); // Calendar view LayoutParams monthParams = new LayoutParams(layoutparams.match_parent, layoutparams.wrap_content); monthCalendarView = new MonthCalendarView(context); initCalendarDate(); monthCalendarView.setOnDatePickUpListener(this); addView(monthCalendarView, monthParams); } private voidinitCalendarDate() {
        int[] nowDay = MyCalendarUtils.getNowDayFromSystem();
        monthCalendarView.setMonth(nowDay[0], nowDay[1]);
        updateTitle();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.pre_month:
                if(null ! = monthCalendarView) { monthCalendarView.moveToPreMonth(); } updateTitle();break;
            case R.id.next_month:
                if(null ! = monthCalendarView) { monthCalendarView.moveToNextMonth(); } updateTitle();break;
        }
    }

    private void updateTitle() {
        if(null ! = title && null ! = monthCalendarView) { title.setText(monthCalendarView.getCurrentYearAndMonth()); } } @Override public void onDatePickUp(MyCalendarBean bean) {if(null ! = onDatePickListener) { onDatePickListener.onDatePick(bean); } } public voidsetOnDatePickListener(OnDatePickListener onDatePickListener) { this.onDatePickListener = onDatePickListener; } public interface OnDatePickListener { void onDatePick(MyCalendarBean bean); }}Copy the code

2, in the layout, very simple

<? 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="match_parent"
    android:background="@color/background_white"
    android:orientation="vertical">

    <com.example.deesonwoo.mysimplecalendar.calendar.SimpleCalendarView
        android:id="@+id/calendarView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </com.example.deesonwoo.mysimplecalendar.calendar.SimpleCalendarView>

</LinearLayout>
Copy the code

3. Call in MainActivity

package com.example.deesonwoo.mysimplecalendar;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

import com.example.deesonwoo.mysimplecalendar.calendar.MyCalendarBean;
import com.example.deesonwoo.mysimplecalendar.calendar.SimpleCalendarView;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_main);

        SimpleCalendarView calendarView = findViewById(R.id.calendarView);
        calendarView.setOnDatePickListener(new SimpleCalendarView.OnDatePickListener() { @Override public void onDatePick(MyCalendarBean bean) { Toast.makeText(MainActivity.this, bean.toString(), Toast.LENGTH_SHORT).show(); }}); }}Copy the code

The end result is the GIF at the beginning of the article.

Five, the subsequent

  • There are a lot of things that can be expanded and modified, so I’ll leave that to you.
  • The source code is linked here