One Android high-performance calendar control, high imitation meizu, and high imitation android
Android's native CalendarView cannot meet our daily development needs. During the process of developing the my note APP, I think we need a high-performance and concise calendar control, I think meizu's calendar style is very suitable, so I plan to renew it.
Github address: https://github.com/huanghaibin-dev/CalendarView
compile 'com.haibin:calendarview:1.0.2'
First:
Before doing this, we need to analyze how meizu designed such a high-performance calendar. We open the display layout boundary in the developer options:
Well, at first I thought the calendar interface was ViewPager + RecyclerView, but obviously it wasn't. If it was RecyclerView, assume that each card has 5x7 = 35 items each month. The root layout of each item is RelativeLayout + 3 textviews. Let's estimate the controls to be loaded during calendar initialization:
Item * 4 (number of controls for each Item) + 8 (week bar) = 420 +
My day, this can not be done, obviously the performance is greatly reduced, let's look at the month control:
Well, it seems that ViewPager + RecyclerView is used here. Every item in RecyclerView is just a control, and the text is drawn in it. here we will analyze it clearly.
We adopt the discount method. The calendar interface and the month card interface both adopt the ViewPager + RecyclerView method. The difference is that all items are drawn using custom ViewCanvas, this performance is not comparable to meizu, but the speed experience is basically the same. Let's take a look at the item code on the calendar interface: Just draw three texts.
Public class CellView extends View {private int mDay = 20; private String mLunar; private String mScheme; private Paint mDayPaint = new Paint (); private Paint mLunarPaint = new Paint (); private Paint mSchemePaint = new Paint (); private Paint mCirclePaint = new Paint (); private int mRadius; private int mCirclePadding; private int mCircleColor; public CellView (Context context) {this (context, null );} Public CellView (Context context, @ Nullable AttributeSet attrs) {super (context, attrs); mDayPaint. setAntiAlias (true); mDayPaint. setColor (Color. BLACK); mDayPaint. setFakeBoldText (true); mDayPaint. setTextAlign (Paint. align. CENTER); mLunarPaint. setAntiAlias (true); mLunarPaint. setColor (Color. GRAY); mLunarPaint. setTextAlign (Paint. align. CENTER); mSchemePaint. setAntiAlias (true); mSchemePaint. setColor (Co Lor. WHITE); mSchemePaint. setFakeBoldText (true); mSchemePaint. setTextAlign (Paint. align. CENTER); mCirclePaint. setAntiAlias (true); mCirclePaint. setStyle (Paint. style. FILL); TypedArray array = context. obtainStyledAttributes (attrs, R. styleable. cellView); mDayPaint. setTextSize (array. getDimensionPixelSize (R. styleable. cellView_cell_day_text_size, 18); mLunarPaint. setTextSize (array. getDimensionPixelSize (R. Styleable. cellView_cell_lunar_text_size, 12); mRadius = (int) array. getDimension (R. styleable. cellView_cell_scheme_radius, 8); mSchemePaint. setTextSize (array. getDimensionPixelSize (R. styleable. cellView_cell_scheme_text_size, 6); mCirclePadding = array. getDimensionPixelSize (R. styleable. cellView_cell_circle_padding, 4); mCirclePaint. setColor (array. getColor (R. styleable. cellView_cell_circle_color, 0xf F16BB7F); array. recycle () ;}@ Override protected void onDraw (Canvas canvas) {super. onDraw (canvas); int width = getWidth (); int height = getHeight (); int w = (width-getPaddingLeft ()-getPaddingRight ()); int h = (height-getPaddingTop ()-getPaddingBottom ()/4; canvas. drawText (String. valueOf (mDay), w/2, 2 * h + getPaddingTop (), mDayPaint); canvas. drawText (mLunar, w/2, 4 * h + getPaddingT Op (), mLunarPaint); if (! TextUtils. isEmpty (mScheme) {canvas. drawCircle (w/2 + mCirclePadding + mDayPaint. getTextSize (), getPaddingTop () + h, mRadius, mCirclePaint); canvas. drawText (mScheme, w/2 + mCirclePadding + mDayPaint. getTextSize (), getPaddingTop () + mRadius/2 + h, mSchemePaint );}} /*** initialize the calendar ** @ param day * @ param lunar calendar * @ param scheme event tag */void init (int day, String lunar, String scheme) {this. mDay = day; this. mLunar = lunar; this. mScheme = scheme;} void setTextColor (int textColor) {mDayPaint. setColor (textColor); mLunarPaint. setColor (textColor);} void setCircleColor (int circleColor) {mCirclePaint. setColor (circleColor); invalidate ();}}
Month card custom View
Public class MonthView extends View {private int mDiff; // number of days from the first day of the week private int mCount; // total number of private int mLastCount; // number of days in the last row private int mLine; // how many rows of private Paint mPaint = new Paint (); private Paint mSchemePaint = new Paint (); private List <Calendar> mSchemes; private Calendar mCalendar; public MonthView (Context context) {this (context, null);} public MonthView (Context context, @ Nullable Attribute Set attrs) {super (context, attrs); mPaint. setAntiAlias (true); mPaint. setTextAlign (Paint. align. CENTER); mSchemePaint. setAntiAlias (true); mSchemePaint. setTextAlign (Paint. align. CENTER); TypedArray array = context. obtainStyledAttributes (attrs, R. styleable. monthView); mPaint. setTextSize (array. getDimensionPixelSize (R. styleable. monthView_month_view_text_size, 12); mSchemePaint. setTextSize (array. getDime NsionPixelSize (R. styleable. monthView_month_view_text_size, 12); mPaint. setColor (array. getColor (R. styleable. monthView_month_view_text_color, Color. BLACK); mSchemePaint. setColor (array. getColor (R. styleable. monthView_month_view_remark_color, Color. RED); array. recycle (); measureLine () ;}@ Override protected void onDraw (Canvas canvas) {super. onDraw (canvas); int width = getWidth (); int height = getHe Ight (); int pLeft = getPaddingLeft (); int w = (width-getPaddingLeft ()-getPaddingRight ()/7; int h = (height-getPaddingTop () -getPaddingBottom ()/6; int d = 0; for (int I = 0; I <mLine; I ++) {if (I = 0) {// The first line for (int j = 0; j <(7-mDiff); j ++) {++ d; canvas. drawText (String. valueOf (j + 1), mDiff * w + j * w + pLeft + w/2, h, isScheme (d )? MSchemePaint: mPaint) ;}} else if (I = mLine-1 & mLastCount! = 0) {int first = mCount-mLastCount + 1; for (int j = 0; j <mLastCount; j ++) {++ d; canvas. drawText (String. valueOf (first), j * w + pLeft + w/2, (I + 1) * h, isScheme (d )? MSchemePaint: mPaint); ++ first ;}} else {int first = I * 7-mDiff + 1; for (int j = 0; j <7; j ++) {++ d; canvas. drawText (String. valueOf (first), j * w + pLeft + w/2, (I + 1) * h, isScheme (d )? MSchemePaint: mPaint); ++ first ;}}}/*** calculate the number of rows */private void measureLine () {int offset = mCount-(7-mDiff ); mLine = 1 + (offset % 7 = 0? 0: 1) + offset/7; mLastCount = offset % 7 ;} /*** initialize the month card * @ param mDiff deviation days * @ param mCount total days of the month * @ param mYear which year * @ param mMonth which month */void init (int mDiff, int mCount, int mYear, int mMonth) {this. mDiff = mDiff; this. mCount = mCount; mCalendar = new Calendar (); mCalendar. setYear (mYear); mCalendar. setMonth (mMonth); measureLine (); invalidate ();} void setSchemes (List <Calendar> mSchemes ){ This. mSchemes = mSchemes;} void setSchemeColor (int schemeColor) {if (schemeColor! = 0) mSchemePaint. setColor (schemeColor); if (schemeColor = 0xff30393E) mSchemePaint. setColor (Color. RED);} private boolean isScheme (int day) {if (mSchemes = null | mSchemes. size () = 0) return false; mCalendar. setDay (day); return mSchemes. contains (mCalendar );}}
Other code is not difficult, calendar algorithm is found on github, for more details, see the repository address: https://github.com/huanghaibin-dev/CalendarView