Android custom calendar
A few days ago, I had nothing to worry about, and I wanted to make some gadgets to play. It took more than a day to get a simple calendar View. It can be divided into the month mode and the week mode. Scroll to view, first look:
The preceding figure shows the month mode. The following is the day of the week:
A simple custom View, and then refresh the View data through the OnpageChangeListener of Viewpager. Viewpager uses the View in a loop. By default, I set five. Unlimited switch between left and right.
The following is a custom CalendarView:
Package com. example. calendar; import android. content. context; import android. graphics. canvas; import android. graphics. color; import android. graphics. paint; import android. util. attributeSet; import android. view. view; public class CalendarView extends View {private static final String TAG = CalendarView;/*** two modes (month and week) */public static final int MONTH_STYLE = 0; public static final int WEEK_STYLE = 1; priva Te static final int TOTAL_COL = 7; private static final int TOTAL_ROW = 6; private Paint mCirclePaint; private Paint mTextPaint; private int mViewWidth; private int mViewHight; private int mCellSpace; private Row rows [] = new Row [TOTAL_ROW]; private int mShowYear; // view displays the year private int mShowMonth; // view displays the month private int mShowDay; // The day when the week style is displayed. protected int defaultStyle = MONTH_STYLE; private static final Int WEEK = 7; public CalendarView (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle); init ();} public CalendarView (Context context, attributeSet attrs) {super (context, attrs); init ();} public CalendarView (Context context) {super (context); init ();} public CalendarView (Context context, int style) {super (context); this. defaultStyle = style; init () ;}@ Overrideprotected void onDr Aw (Canvas canvas) {super. onDraw (canvas); fillDate (); for (int I = 0; I <TOTAL_ROW; I ++) {if (rows [I]! = Null) rows [I]. drawCells (canvas, I) ;}} private void init () {mTextPaint = new Paint (Paint. ANTI_ALIAS_FLAG); mCirclePaint = new Paint (Paint. ANTI_ALIAS_FLAG); mCirclePaint. setStyle (Paint. style. FILL); mCirclePaint. setColor (Color. parseColor (# F24949); initDate ();} private void initDate () {if (defaultStyle = MONTH_STYLE) {mShowYear = DateUtil. getYear (); mShowMonth = DateUtil. getMonth (); mShowDay = 1;} else {int time [] = DateUtil. getperviusweeksunday (); mShowYear = time [0]; mShowMonth = time [1]; mShowDay = time [2] ;}@overrideprotected void onSizeChanged (int w, int h, int oldw, int oldh) {super. onSizeChanged (w, h, oldw, oldh); mViewWidth = w; mViewHight = h; mCellSpace = Math. min (mViewHight/TOTAL_ROW, mViewWidth/TOTAL_COL); mTextPaint. setTextSize (mCellSpace/3);} // group class Row {public Cell [] cells = new Cell [TOTA Rochelle Col]; public void drawCells (Canvas canvas, int j) {for (int I = 0; I <cells. length; I ++) {if (cells [I]! = Null) cells [I]. drawSelf (canvas, I, j) ;}}// Cell class Cell {public String text; public State state; public Cell (String text, State state) {super (); this. text = text; this. state = state;} public void setText (String text) {this. text = text;} // draw a cell. If you need to customize the color, you can modify public void drawSelf (Canvas canvas, int I, int j) {switch (state) {case CURRENT_MONTH_DAY: mTextPaint. setColor (Color. parseColor (#80000000); break; case NEXT_MONTH_DAY: case PAST_MONTH_DAY: mTextPaint. setColor (Color. parseColor (#40000000); break; case TODAY: mTextPaint. setColor (Color. parseColor (# fffffe); canvas. drawCircle (float) (mCellSpace * (I + 0.45), (float) (j + 0.8) * mCellSpace), mCellSpace/2, mCirclePaint); break ;} // draw a text canvas. drawText (text, I * mCellSpace + mTextPaint. measureText (11), (j + 1) * mCellSpace-mTextPaint. measureText (text, 0, 1)/2, mTextPaint) ;}} enum State {CURRENT_MONTH_DAY, PAST_MONTH_DAY, NEXT_MONTH_DAY, TODAY ;} /*** fill date data */private void fillDate () {if (defaultStyle = MONTH_STYLE) {fillMonthDate () ;}else {fillWeekDate ();}} /*** fill in the data in week mode * get the date of Sunday by default through the current date, and then fill in the date in sequence */private void fillWeekDate () {int currentMonthDays = DateUtil. getMonthDays (mShowYear, mShowMonth); rows [0] = new Row (); if (mShowDay + WEEK-1> currentMonthDays) {mShowMonth + = 1 ;} for (int I = 0; I <TOTAL_COL; I ++) {mShowDay + = 1; if (mShowDay> currentMonthDays) {mShowDay = 1;} if (mShowDay = DateUtil. getCurrentMonthDays () & mShowYear = DateUtil. getYear () & mShowMonth = DateUtil. getMonth () {rows [0]. cells [I] = new Cell (mShowDay +, State. TODAY); continue;} rows [0]. cells [I] = new Cell (mShowDay +, State. CURRENT_MONTH_DAY );}} /*** fill data in month mode * Get the day of the first day of a month through getWeekDayFromDate, which is the day of the week, and then calculate the positions of all dates * and fill in */private void fillMonthDate () in sequence () {int monthDay = DateUtil. getCurrentMonthDays (); int lastMonthDays = DateUtil. getMonthDays (mShowYear, mShowMonth-1); int currentMonthDays = DateUtil. getMonthDays (mShowYear, mShowMonth); int firstDayWeek = DateUtil. getWeekDayFromDate (mShowYear, mShowMonth); boolean isCurrentMonth = false; if (mShowYear = DateUtil. getYear () & mShowMonth = DateUtil. getMonth () {isCurrentMonth = true;} int time = 0; for (int j = 0; j <TOTAL_ROW; j ++) {rows [j] = new Row (); for (int I = 0; I <TOTAL_COL; I ++) {int postion = I + j * TOTAL_COL; if (postion> = firstDayWeek & postion <firstDayWeek + currentMonthDays) {time ++; if (isCurrentMonth & time = monthDay) {rows [j]. cells [I] = new Cell (time +, State. TODAY); continue;} rows [j]. cells [I] = new Cell (time +, State. CURRENT_MONTH_DAY); continue;} else if (postion <firstDayWeek) {rows [j]. cells [I] = new Cell (lastMonthDays-(firstDayWeek-postion-1) +, State. PAST_MONTH_DAY); continue;} else if (postion> = firstDayWeek + currentMonthDays) {rows [j]. cells [I] = new Cell (postion-firstDayWeek-currentMonthDays + 1) +, State. NEXT_MONTH_DAY) ;}}}// call the switchover pager to refresh public void update (int year, int month, int day) {this. mShowMonth = month; this. mShowYear = year; this. mShowDay = day; invalidate () ;}@ Overrideprotected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {int width = measure (widthMeasureSpec); int height = measure (heightMeasureSpec ); int d = Math. min (width, height); setMeasuredDimension (d, d);} protected int measure (int measureSpec) {int size = MeasureSpec. getSize (measureSpec); return size;} // to facilitate viewPager's production of multiple CalendarViewpublic static CalendarView [] createCalendarViewsForPager (Context context, int count, int style) {CalendarView [] views = new CalendarView [count]; for (int I = 0; I <count; I ++) {views [I] = new CalendarView (context, style);} return views;} public static CalendarView [] createCalendarViewsForPager (Context context, int count) {CalendarView [] views = new CalendarView [count]; for (int I = 0; I <count; I ++) {views [I] = new CalendarView (context, CalendarView. MONTH_STYLE) ;}return views ;}}
I have rewritten ViewPagerAdapter. The CalendarViewPagerAdapter implements the infinite loop function required by the calendar. If you want to use it, you can inherit it.
package com.example.calendar;import android.os.Parcelable;import android.support.v4.view.PagerAdapter;import android.support.v4.view.ViewPager;import android.view.View;public class CalendarViewPagerAdapter extends PagerAdapter {private View[] views;public CalendarViewPagerAdapter(View[] views) {super();this.views = views;}@Overridepublic void finishUpdate(View arg0) {}@Overridepublic void notifyDataSetChanged() {super.notifyDataSetChanged();}@Overridepublic int getCount() {return Integer.MAX_VALUE;}@Overridepublic Object instantiateItem(View arg0, int arg1) {if (((ViewPager) arg0).getChildCount() == views.length) {((ViewPager) arg0).removeView(views[arg1 % views.length]);}((ViewPager) arg0).addView(views[arg1 % views.length], 0);return views[arg1 % views.length];}@Overridepublic boolean isViewFromObject(View arg0, Object arg1) {return arg0 == (arg1);}@Overridepublic Parcelable saveState() {return null;}@Overridepublic void destroyItem(View arg0, int arg1, Object arg2) {// TODO Auto-generated method stub}@Overridepublic void startUpdate(View arg0) {}}
Then, in order to update the data when the CalendarView slides, I overwrite the OnPageChangeListener method. Reserve a method for the activity interface to callback onPageSelected (int year, int month, int day ).
package com.example.calendar;import android.support.v4.view.ViewPager.OnPageChangeListener;public class CalendarViewPagerLisenter implements OnPageChangeListener {private SildeDirection mDirection = SildeDirection.NO_SILDE;int mCurrIndex = 498;private static final int WEEK = 7;private int mShowYear;private int mShowMonth;private int mShowDay = 1;private CalendarView[] mShowViews;private int style;public CalendarViewPagerLisenter(CalendarView[] mShowViews) {super();this.mShowViews = mShowViews;}public CalendarViewPagerLisenter(CalendarView[] mShowViews, int style) {super();this.mShowViews = mShowViews;this.style = style;initDate();}@Overridepublic void onPageSelected(int arg0) {measureDirection(arg0);updateCalendarView(arg0);onPageSelected(mShowYear, mShowMonth, mShowDay);}private void updateCalendarView(int arg0) {if (style == CalendarView.MONTH_STYLE)updateMonthStyleCalendarView();else if ((style == CalendarView.WEEK_STYLE))updateWeekStyleCalendarView();mShowViews[arg0 % mShowViews.length].update(mShowYear, mShowMonth,mShowDay);}private void updateWeekStyleCalendarView() {//int[] time = new int[3];if (mDirection == SildeDirection.RIGHT) {int currentMonthDays = DateUtil.getMonthDays(mShowYear,mShowMonth);if(mShowDay + WEEK > currentMonthDays){ if(mShowMonth == 12){ mShowMonth = 1; mShowYear += 1; }else{ mShowMonth += 1; } mShowDay = WEEK -currentMonthDays + mShowDay; return;}mShowDay += WEEK;} else if (mDirection == SildeDirection.LEFT) {int lastMonthDays = DateUtil.getMonthDays(mShowYear, mShowMonth);if(mShowDay - WEEK < 1){if(mShowMonth == 1){mShowMonth = 12;mShowYear -= 1;}else{mShowMonth -= 1;}mShowDay = lastMonthDays - WEEK + mShowDay;return;}mShowDay -= WEEK;}mDirection = SildeDirection.NO_SILDE;}private void updateMonthStyleCalendarView() {if (mDirection == SildeDirection.RIGHT) {if (mShowMonth == 12) {mShowMonth = 1;mShowYear += 1;} else {mShowMonth += 1;}} else if (mDirection == SildeDirection.LEFT) {if (mShowMonth == 1) {mShowMonth = 12;mShowYear -= 1;} else {mShowMonth -= 1;}}mDirection = SildeDirection.NO_SILDE;}private void measureDirection(int arg0) {if (arg0 > mCurrIndex) {mDirection = SildeDirection.RIGHT;} else if (arg0 < mCurrIndex) {mDirection = SildeDirection.LEFT;}mCurrIndex = arg0;}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {}@Overridepublic void onPageScrollStateChanged(int arg0) {}public void onPageSelected(int year, int month, int day) {}enum SildeDirection {RIGHT, LEFT, NO_SILDE;}private void initDate(){if(style == CalendarView.MONTH_STYLE){mShowYear = DateUtil.getYear();mShowMonth = DateUtil.getMonth();mShowDay = 1;}else if(style == CalendarView.WEEK_STYLE){int time[] = DateUtil.getPerviousWeekSunday();mShowYear = time[0];mShowMonth = time[1];mShowDay = time[2];}onPageSelected(mShowYear, mShowMonth, mShowDay);}public void setData(int style, CalendarView[] mShowViews){this.style = style;this.mShowViews = mShowViews;}}
This is a simple demo, but I can encapsulate it and call it directly. If you need it, you can download it directly.