今天是周六,趁着还有多余的空闲,把这周的干活拿出来晒一晒。首先看项目的截图。
这个就是项目的截图,很明显这是一个日历,由于有特殊的需求,比如每个日期需要添加点击事件,分别为每天设置不同的考勤信息,类似于这种只能用自定义view去实现。
分析:
1.首先观察日历每一行的背景都是岔开的,这种如何实现。
2.每周六跟周日的日期颜色不一样。
3.特殊日期有圆形图形包起来。
4.星期要跟日期对应起来。
5.需要考虑如果一个月只有28天的话,就不需要绘制那么多行。
技术难点:
1.关于坐标的计算,这个是比较麻烦的,因为涉及到点击事件,还涉及到日期与星期的对应。
2.屏幕适配,坐标的计算以及字体的大小需要根据屏幕的适配进行调整。
3.绘制文字圆形背景的时候,如何保证文字在圆圈的中间。
5.日期切换,数据及逻辑处理等等。
我在拿到项目的需求后,首先我也在网上找了下,也有很多成熟的方案,但是我还是想自己写一些,第一给人的感觉这个应该是不难的,但是实际自己动起手来才发现,事实并不如此。当中的坑是你想不到的。但是只有自己真正的写出来才会进步,我感觉能把这个自己写出来,自定义view方面也都不是什么难事了。
解析思路:
1.为了避免背景被文字覆盖,所以需要先要绘制背景。
2.计算每个月有多少天,每个月的第一天是周几。
3.绘制文字,在绘制文字的同时,需要给文字绘制圆形背景,避免圆形背景覆盖文字。
4.添加点击事件,判断点击的坐标点是在哪个点的范围内。
(这些代码大家复制过去直接能用了)
代码:
时间处理的工具类:
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.TimeZone; /* * @项目名: Zhukeyunfu * @包名: com.eben.zhukeyunfu.Activity.utils * @文件名: DateUtils * @创建者: Administrator * @创建时间: 2016/11/4 15:44 * @描述: TODO */ public class DateUtils { private static final String TAG = "DateUtils"; private static String mYear; // 当前年 private static String mMonth; // 月 private static String mDay; private static String mWay; /** * 获取当前日期几月几号 */ public static String getDateString() { final Calendar c = Calendar.getInstance(); c.setTimeZone(TimeZone.getTimeZone("GMT+8:00")); mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份 mDay = String.valueOf(c.get(Calendar.DAY_OF_MONTH));// 获取当前月份的日期号码 if(Integer.parseInt(mDay) > MaxDayFromDay_OF_MONTH(Integer.parseInt(mYear),(Integer.parseInt(mMonth)))){ mDay = String.valueOf(MaxDayFromDay_OF_MONTH(Integer.parseInt(mYear),(Integer.parseInt(mMonth)))); } return mMonth + "月" + mDay + "日"; } /** * 获取当前年月日 * * @return */ public static String StringData() { final Calendar c = Calendar.getInstance(); c.setTimeZone(TimeZone.getTimeZone("GMT+8:00")); mYear = String.valueOf(c.get(Calendar.YEAR));// 获取当前年份 mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份 mDay = String.valueOf(c.get(Calendar.DAY_OF_MONTH));// 获取当前月份的日期号码 if(Integer.parseInt(mDay) > MaxDayFromDay_OF_MONTH(Integer.parseInt(mYear),(Integer.parseInt(mMonth)))){ mDay = String.valueOf(MaxDayFromDay_OF_MONTH(Integer.parseInt(mYear),(Integer.parseInt(mMonth)))); } return mYear + "-" + (mMonth.length()==1?"0"+mMonth:mMonth) + "-" + (mDay.length()==1?"0"+mDay:mDay); } /** * 根据当前日期获得是星期几 * * @return */ public static String getWeek(String time) { String Week = ""; SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Calendar c = Calendar.getInstance(); try { c.setTime(format.parse(time)); } catch (ParseException e) { e.printStackTrace(); } if (c.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) { Week += "周天"; } if (c.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) { Week += "周一"; } if (c.get(Calendar.DAY_OF_WEEK) == Calendar.TUESDAY) { Week += "周二"; } if (c.get(Calendar.DAY_OF_WEEK) == Calendar.WEDNESDAY) { Week += "周三"; } if (c.get(Calendar.DAY_OF_WEEK) == Calendar.THURSDAY) { Week += "周四"; } if (c.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) { Week += "周五"; } if (c.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) { Week += "周六"; } return Week; } /** * 获取今天往后一周的日期(几月几号) */ public static List<String> getSevendate() { List<String> dates = new ArrayList<String>(); final Calendar c = Calendar.getInstance(); c.setTimeZone(TimeZone.getTimeZone("GMT+8:00")); for (int i = 0; i < 7; i++) { mYear = String.valueOf(c.get(Calendar.YEAR));// 获取当前年份 mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份 mDay = String.valueOf(c.get(Calendar.DAY_OF_MONTH) + i);// 获取当前日份的日期号码 if(Integer.parseInt(mDay) > MaxDayFromDay_OF_MONTH(Integer.parseInt(mYear),(i+1))){ mDay = String.valueOf(MaxDayFromDay_OF_MONTH(Integer.parseInt(mYear),(i+1))); } String date = mMonth + "月" + mDay + "日"; dates.add(date); } return dates; } /** * 获取今天往后一周的集合 */ public static List<String> get7week() { String week = ""; List<String> weeksList = new ArrayList<String>(); List<String> dateList = get7date(); for (String s : dateList) { if (s.equals(StringData())) { week = "今天"; } else { week = getWeek(s); } weeksList.add(week); } return weeksList; } public static List<String> get7date() { List<String> dates = new ArrayList<String>(); final Calendar c = Calendar.getInstance(); c.setTimeZone(TimeZone.getTimeZone("GMT+8:00")); java.text.SimpleDateFormat sim = new java.text.SimpleDateFormat( "yyyy-MM-dd"); String date = sim.format(c.getTime()); dates.add(date); for (int i = 0; i < 6; i++) { c.add(java.util.Calendar.DAY_OF_MONTH, 1); date = sim.format(c.getTime()); dates.add(date); } return dates; } /**得到当年当月的最大日期**/ public static int MaxDayFromDay_OF_MONTH(int year,int month){ Calendar time=Calendar.getInstance(); time.clear(); time.set(Calendar.YEAR,year); time.set(Calendar.MONTH,month-1);//注意,Calendar对象默认一月为0 int day=time.getActualMaximum(Calendar.DAY_OF_MONTH);//本月份的天数 return day; } public static List<String> get7dateBefore() { List<String> dates = new ArrayList<String>(); Long currenttime=System.currentTimeMillis(); for(int i=0;i<=6;i++){ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Long time=new Long(currenttime-24*3600*1000*i); String d = format.format(time); dates.add(d); } return dates; } /*返回最近的12个月的月份集合*/ public static List<String> get12Month(){ List<String> dates = new ArrayList<String>(); final Calendar c = Calendar.getInstance(); c.setTimeZone(TimeZone.getTimeZone("GMT+8:00")); mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份 int month= Integer.parseInt(mMonth); for (int i=0;i<12;i++){ if(month-i>0){ dates.add(month-i+""); } else if (month-i==0){ dates.add(12+""); }else if (month-i<0){ dates.add(Math.abs(month-i)+""); } } return dates; } /** * 1-6 代表星期一至星期六 0 代表星期日 * 如果返回 -1 表示参数不正确 */ public static int calWeek(int y, int m, int d) { if (m < 1 || m > 12 || d < 1 || d > 31) return -1; if (m == 1) { m = 13; y--; } else if (m == 2) { m = 14; y--; } int c = y / 100; y = y - c * 100; int week = y + y / 4 + c / 4 - 2 * c + 26 * (m + 1) / 10 + d - 1; week %= 7; week = week < 0 ? week + 7 : week; return week; } /** * 获取当月的 天数 * */ public static int getCurrentMonthDay() { Calendar a = Calendar.getInstance(); a.set(Calendar.DATE, 1); a.roll(Calendar.DATE, -1); int maxDate = a.get(Calendar.DATE); return maxDate; } /*获取当前是哪一年*/ public static int getYear(){ final Calendar c = Calendar.getInstance(); c.setTimeZone(TimeZone.getTimeZone("GMT+8:00")); /*mYear = String.valueOf(c.get(Calendar.YEAR));// 获取当前年份 mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份 mDay = String.valueOf(c.get(Calendar.DAY_OF_MONTH));// 获取当前月份的日期号码*/ return c.get(Calendar.YEAR); } /*获取当前的月份*/ public static int getMonth(){ final Calendar c = Calendar.getInstance(); c.setTimeZone(TimeZone.getTimeZone("GMT+8:00")); /*mYear = String.valueOf(c.get(Calendar.YEAR));// 获取当前年份 mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份 mDay = String.valueOf(c.get(Calendar.DAY_OF_MONTH));// 获取当前月份的日期号码*/ return c.get(Calendar.MONTH) + 1; } /** * 根据年 月 获取对应的月份 天数 * */ public static int getDaysByYearMonth(int year, int month) { Calendar a = Calendar.getInstance(); a.set(Calendar.YEAR, year); a.set(Calendar.MONTH, month - 1); a.set(Calendar.DATE, 1); a.roll(Calendar.DATE, -1); int maxDate = a.get(Calendar.DATE); return maxDate; } }
自定义View的代码,因为是做项目的,所以没办法把所有的代码都放进来,后面会建一个文件夹打包把所有需要的放一起,给大家下载使用。
package com.eben.zhukeyunfu.Activity.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.Toast; import com.eben.zhukeyunfu.Activity.utils.DateUtils; import com.eben.zhukeyunfu.R; import java.util.List; /* * @项目名: Zhukeyunfu * @包名: com.eben.zhukeyunfu.Activity.view * @文件名: MyCalendar * @创建者: Administrator * @创建时间: 2017/2/20 9:29 * @描述: TODO */ public class MyCalendar extends View { private static final String TAG = "MyCalendar"; private int mViewWidth; private int mViewHeight; private Paint mPaint; private String[] mWeek; private Paint whiteBgpaint; private Paint grayBgpaint; private Paint mBlackPaint; private float textHight; private Paint kuanggongBgpaint; private List<Integer> mKuanggong; private List<Integer> mQiantui; private List<Integer> mZaotui; private List<Integer> mChiDao; private List<Integer> mWeiQianDao; private Paint zaotuipaint; private Paint chidaopaint; private Paint weiqiandaopaint; private Paint weiqiantuipaint; private int mWeekFirst1; private int year; private int month; private int mMonthdays; private Paint grayTextpaint; private int mZiti20; private int mZiti27; private int mZiti25; private float mTextHeight; private float mTextWidth; public MyCalendar(Context context) { super(context); } public MyCalendar(Context context, AttributeSet attrs) { super(context, attrs); initWeek(); //initdata(); initZiTi(); initBluePaint(); initGrayPaint(); initGrayTextPaint(); initWhiteBackgroundPaint(); initGrayBackgroundPaint(); initKuangGongPaint(); initWeiQianTuiPaint(); initWeiQianDaoPaint(); initChiDaoPaint(); initZaoTuiPaint(); } private void initZiTi() { mZiti20 = sp2px(getContext(),13); mZiti27 =sp2px(getContext(),15);; mZiti25 =sp2px(getContext(),17);; Log.d(TAG,mZiti20+"-----"+mZiti27+"----"+mZiti25); } /*将ps转成sp保证字体大小不变*/ //注意:这里的paint设置字体大小是非常重要的,但是grayBgpaint.setTextSize(20); 这里的20是px,所以需要将sp转成ps转成 public float px2sp(Context context, int pxValue) { /**/ DisplayMetrics dm =context.getResources().getDisplayMetrics(); int w_screen = dm.widthPixels; int h_screen = dm.heightPixels; int dpi=dm.densityDpi; // Toast.makeText(context,"屏幕尺寸2:宽度 = " + w_screen + "高度 = " + h_screen + "密度 = " + dm.densityDpi,Toast.LENGTH_SHORT).show(); Log.i(TAG, "屏幕尺寸2:宽度 = " + w_screen + "高度 = " + h_screen + "密度 = " + dm.densityDpi); /*pxValue 传入 25 27 29*/ return 240*pxValue/260; } /** * 将sp值转换为px值,保证文字大小不变 * (DisplayMetrics类中属性scaledDensity) * @return */ public int sp2px(Context context, float spValue) { final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; return (int) (spValue * fontScale + 0.5f); } private void initWeek() { mWeek = new String[]{"日", "一", "二", "三", "四", "五", "六"}; } /*测量*/ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //super.onMeasure(widthMeasureSpec, heightMeasureSpec); /*特别注意,此处必须要自己进行测量,否则系统会默认讲 wrap_cotent与match_parent视为相同,也就是会填充整个布局*/ setMeasuredDimension(measure(widthMeasureSpec), measure(heightMeasureSpec)); getViewXY(); } /*自己测量view的宽高*/ private int measure(int measureSpec) { int result = 0; //分别获取测量模式 和 测量大小 int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); //如果是精确度模式,呢就按xml中定义的来 if (specMode == MeasureSpec.EXACTLY) { result = specSize; } //如果是最大值模式,就按我们定义的来 else if (specMode == MeasureSpec.AT_MOST) { result = mViewWidth * 6 / 8; } return result; } /*获取自定义view的宽度*/ private void getViewXY() { mViewWidth = getMeasuredWidth(); mViewHeight = getMeasuredHeight(); } /*根据paint获取绘制文字的宽高*/ public float getFontHeight(Paint paint) { Paint.FontMetrics fm = paint.getFontMetrics(); return (float) (Math.ceil(fm.descent - fm.top) + 2); } /*画图*/ @Override protected void onDraw(Canvas canvas) { /*先画背景*/ drawbackWeekground(canvas); /*获取每个竖直列的坐标*/ float x1 = mViewWidth / 8; float y1 = x1 / 2; Log.d(TAG, "文字的高度" + textHight / 2); Log.d(TAG, "y1-----" + y1); Log.d(TAG, "x1-----" + x1); /*获取屏幕的宽度*/ /*画文字周日~周六*/ for (int i = 0; i < 7; i++) { canvas.drawText(mWeek[i], x1 * (i + 1) , y1, mPaint); } /*获取当前月份的天数*/ //mMonthdays = DateUtils.getCurrentMonthDay(); /*获取当前月份的第一天是星期几*/ /* int year = DateUtils.getYear(); int month = DateUtils.getMonth();*/ Log.d(TAG, "当前月份的第一天是ondraw" + mWeekFirst1); if (mMonthdays == 28 && mWeekFirst1 == 0) { /*那么只需要画四行,否则需要❀五行数字*/ /*如果一个月只有28天,并且第一天刚好是周末,那么就刚刚好满足4行共28个数字,那么直需要画四行背景*/ drawbackground(canvas,4); /*这样的话,就依次画数字就行*/ } else { /*继续画背景,其他情况,一个月份就需要画5行背景*/ drawbackground(canvas,5); } /*画五行数字*/ int j = 1; for (int i = 1; i <= mMonthdays; i++) { /*准备开始画数字*/ /*如果是10或者20的,就画个圆*/ /*缺勤的天数处理*/ /*获取圆的坐标*/ float cx = x1 * (mWeekFirst1 + 1); float cy = x1 * j+y1 ; /*获取文字的宽高*/ Paint.FontMetrics fm = kuanggongBgpaint.getFontMetrics(); mTextWidth = kuanggongBgpaint.measureText(i + ""); mTextHeight = fm.bottom - fm.top; if (mKuanggong!=null&&mKuanggong.contains(i)) { /*画圆*/ canvas.drawCircle(cx, cy, mTextHeight / 2 + 8, kuanggongBgpaint); canvas.drawText(i + "", cx , cy+mTextHeight /4, whiteBgpaint); } else if (mChiDao!=null&&mChiDao.contains(i)) { /*迟到*/ canvas.drawCircle(cx, cy, mTextHeight /2 + 8, chidaopaint); canvas.drawText(i + "", cx , cy+mTextHeight /4, whiteBgpaint); } else if (mQiantui!=null&&mQiantui.contains(i)) { /*未签到*/ canvas.drawCircle(cx, cy, mTextHeight / 2 + 8, weiqiandaopaint); canvas.drawText(i + "", cx , cy+mTextHeight /4, whiteBgpaint); } else if (mZaotui!=null&&mZaotui.contains(i)) { /**/ canvas.drawCircle(cx, cy, mTextHeight / 2 + 8, zaotuipaint); canvas.drawText(i + "", cx , cy+mTextHeight /4, whiteBgpaint); } else if (mQiantui!=null&&mQiantui.contains(i)) { /*未签退*/ canvas.drawCircle(cx, cy, mTextHeight / 2 + 8, weiqiantuipaint); canvas.drawText(i + "", cx , cy+mTextHeight /4, whiteBgpaint); } else { /*处理周六与周日的文字颜色问题paint grayTextpaint*/ if (mWeekFirst1==0||mWeekFirst1==6){ canvas.drawText(i + "", cx , cy+mTextHeight /4, grayTextpaint); }else { canvas.drawText(i + "", cx , cy+mTextHeight /4, mBlackPaint); } } mWeekFirst1++; if (mWeekFirst1 == 7) { mWeekFirst1 = 0; j++; } } } /*画背景*/ private void drawbackWeekground(Canvas canvas){ /*背景1*/ RectF oval1 = new RectF(0, 0, mViewWidth, mViewWidth / 8);// 设置个新的长方形 canvas.drawRoundRect(oval1, 0, 0, whiteBgpaint);//第二个参数是x半径,第三个参数是y半径 } /*画背景*/ private void drawbackground(Canvas canvas,int hangshu) { /*背景2*/ RectF oval2 = new RectF(0, mViewWidth / 8, mViewWidth, mViewWidth * 2 / 8);// 设置个新的长方形 canvas.drawRoundRect(oval2, 0, 0, grayBgpaint);//第二个参数是x半径,第三个参数是y半径 /*背景3*/ RectF oval3 = new RectF(0, mViewWidth * 2 / 8, mViewWidth, mViewWidth * 3 / 8);// 设置个新的长方形 canvas.drawRoundRect(oval3, 0, 0, whiteBgpaint);//第二个参数是x半径,第三个参数是y半径 /*背景4*/ RectF oval4 = new RectF(0, mViewWidth * 3 / 8, mViewWidth, mViewWidth * 4 / 8);// 设置个新的长方形 canvas.drawRoundRect(oval4, 0, 0, grayBgpaint);//第二个参数是x半径,第三个参数是y半径 /*背景5*/ RectF oval5 = new RectF(0, mViewWidth * 4 / 8, mViewWidth, mViewWidth * 5 / 8);// 设置个新的长方形 canvas.drawRoundRect(oval5, 0, 0, whiteBgpaint);//第二个参数是x半径,第三个参数是y半径 if(hangshu==4){ return; }else if(hangshu==5){ /*背景6*/ RectF oval6 = new RectF(0, mViewWidth * 5 / 8, mViewWidth, mViewWidth * 6 / 8);// 设置个新的长方形 canvas.drawRoundRect(oval6, 0, 0, grayBgpaint);//第二个参数是x半径,第三个参数是y半径 } } /*触摸处理*/ @Override public boolean onTouchEvent(MotionEvent event) { float y = event.getY(); float x = event.getX(); float lineheight=mViewWidth / 8; float row=x/lineheight; mWeekFirst1=DateUtils.calWeek(year, month, 1); Log.d(TAG, "当前月份的第一天是ontouch" + mWeekFirst1); //获取手指的操作--》按下、移动、松开 Log.d(TAG, "点击了坐标 x = "+x+" y ="+y); int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN://按下 Log.i(TAG, "ACTION_DOWN"); if (y/lineheight>0.0f&&y/lineheight<1.0f){ Log.d(TAG, "onTouchEvent: 第一行"); } else if (y/lineheight>1.0f&&y/lineheight<2.0f){ Log.d(TAG, "onTouchEvent: 第二行"); for (int i=1;i<=7;i++){ if (x<i*lineheight+lineheight/2&&x>=i*lineheight-lineheight/2){ Log.d(TAG,"点击了第2行的,第"+(i)+"列"); Log.d(TAG, "onTouchEvent: 实际坐标点"+(i-mWeekFirst1)); if (i-mWeekFirst1>0){ Toast.makeText(getContext(),"点击了"+month+"月"+(i-mWeekFirst1)+"日",Toast.LENGTH_SHORT).show(); } break; } } } else if (y/lineheight>2.0f&&y/lineheight<3.0f){ Log.d(TAG, "onTouchEvent: 第三行"); for (int i=1;i<=7;i++){ if (x<i*lineheight+lineheight/2&&x>=i*lineheight-lineheight/2){ Log.d(TAG,"点击了第3行的,第"+(i)+"列"); Log.d(TAG, "onTouchEvent: 实际坐标点"+(7-mWeekFirst1+i)); Toast.makeText(getContext(),"点击了"+month+"月"+(7-mWeekFirst1+i)+"日",Toast.LENGTH_SHORT).show(); break; } } } else if (y/lineheight>3.0f&&y/lineheight<4.0f){ Log.d(TAG, "onTouchEvent: 第四行"); for (int i=1;i<=7;i++){ if (x<i*lineheight+lineheight/2&&x>=i*lineheight-lineheight/2){ Log.d(TAG,"点击了第4行的,第"+(i)+"列"); Log.d(TAG, "onTouchEvent: 实际坐标点"+(7-mWeekFirst1+i+7)); Toast.makeText(getContext(),"点击了"+month+"月"+(7-mWeekFirst1+i+7)+"日",Toast.LENGTH_SHORT).show(); break; } } } else if (y/lineheight>4.0f&&y/lineheight<5.0f){ Log.d(TAG, "onTouchEvent: 第五行"); for (int i=1;i<=7;i++){ if (x<i*lineheight+lineheight/2&&x>=i*lineheight-lineheight/2){ Log.d(TAG,"点击了第5行的,第"+(i)+"列"); Log.d(TAG, "onTouchEvent: 实际坐标点"+(7-mWeekFirst1+i+7*2)); Toast.makeText(getContext(),"点击了"+month+"月"+(7-mWeekFirst1+i+7*2)+"日",Toast.LENGTH_SHORT).show(); break; } } } else if (y/lineheight>5.0f&&y/lineheight<6.0f){ Log.d(TAG, "onTouchEvent: 第六行"); for (int i=1;i<=7;i++){ if (x<i*lineheight+lineheight/2&&x>=i*lineheight-lineheight/2){ Log.d(TAG,"点击了第6行的,第"+(i)+"列"); Log.d(TAG, "onTouchEvent: 实际坐标点"+(7-mWeekFirst1+i+7*3)); if (7-mWeekFirst1+i+7*3<=mMonthdays){ Toast.makeText(getContext(),"点击了"+month+"月"+(7-mWeekFirst1+i+7*3)+"日",Toast.LENGTH_SHORT).show(); } break; } } }else{ Log.d(TAG, "onTouchEvent: 无效区域"); } break; case MotionEvent.ACTION_MOVE://移动 break; case MotionEvent.ACTION_UP://松开 break; } return true; } /*初始化画笔paint*/ private void initZaoTuiPaint() { zaotuipaint = new Paint(); zaotuipaint.setAntiAlias(true);//去锯齿 zaotuipaint.setColor(getResources().getColor(R.color.zaotui)); zaotuipaint.setTextSize(mZiti20); // 消除字体锯齿 zaotuipaint.setFlags(Paint.ANTI_ALIAS_FLAG); } private void initChiDaoPaint() { chidaopaint = new Paint(); chidaopaint.setAntiAlias(true);//去锯齿 chidaopaint.setColor(getResources().getColor(R.color.chidao)); chidaopaint.setTextSize(mZiti20); // 消除字体锯齿 chidaopaint.setFlags(Paint.ANTI_ALIAS_FLAG); } private void initWeiQianDaoPaint() { weiqiandaopaint = new Paint(); weiqiandaopaint.setAntiAlias(true);//去锯齿 weiqiandaopaint.setColor(getResources().getColor(R.color.weiqioandao)); weiqiandaopaint.setTextSize(mZiti20); // 消除字体锯齿 weiqiandaopaint.setFlags(Paint.ANTI_ALIAS_FLAG); } private void initWeiQianTuiPaint() { weiqiantuipaint = new Paint(); weiqiantuipaint.setAntiAlias(true);//去锯齿 weiqiantuipaint.setColor(getResources().getColor(R.color.weiqioantui)); weiqiantuipaint.setTextSize(mZiti20); // 消除字体锯齿 weiqiantuipaint.setFlags(Paint.ANTI_ALIAS_FLAG); } private void initKuangGongPaint() { kuanggongBgpaint = new Paint(); kuanggongBgpaint.setAntiAlias(true);//去锯齿 kuanggongBgpaint.setColor(getResources().getColor(R.color.kuanggong)); kuanggongBgpaint.setTextSize(mZiti20); // 消除字体锯齿 kuanggongBgpaint.setFlags(Paint.ANTI_ALIAS_FLAG); } private void initBluePaint() { mPaint = new Paint(); mPaint.setAntiAlias(true);//去锯齿 mPaint.setColor(getResources().getColor(R.color.skyBlue)); mPaint.setTextAlign(Paint.Align.CENTER); mPaint.setTextSize(mZiti25); // 消除字体锯齿 mPaint.setFlags(Paint.ANTI_ALIAS_FLAG); textHight = getFontHeight(mPaint); } private void initGrayPaint() { mBlackPaint = new Paint(); mBlackPaint.setAntiAlias(true);//去锯齿 mBlackPaint.setColor(Color.BLACK); mBlackPaint.setTextSize(mZiti27); mBlackPaint.setTextAlign(Paint.Align.CENTER); // 消除字体锯齿 mBlackPaint.setFlags(Paint.ANTI_ALIAS_FLAG); } private void initGrayBackgroundPaint() { grayBgpaint = new Paint(); grayBgpaint.setAntiAlias(true);//去锯齿 grayBgpaint.setColor(getResources().getColor(R.color.grayBG)); grayBgpaint.setTextSize(mZiti20); // 消除字体锯齿 grayBgpaint.setFlags(Paint.ANTI_ALIAS_FLAG); } private void initWhiteBackgroundPaint() { whiteBgpaint = new Paint(); whiteBgpaint.setAntiAlias(true);//去锯齿 whiteBgpaint.setColor(Color.WHITE); whiteBgpaint.setTextSize(mZiti20); whiteBgpaint.setTextAlign(Paint.Align.CENTER); // 消除字体锯齿 whiteBgpaint.setFlags(Paint.ANTI_ALIAS_FLAG); } private void initGrayTextPaint() { grayTextpaint = new Paint(); grayTextpaint.setAntiAlias(true);//去锯齿 grayTextpaint.setColor(getResources().getColor(R.color.grayText)); grayTextpaint.setTextSize(mZiti27); /*设置文字的重点点坐标开始画*/ grayTextpaint.setTextAlign(Paint.Align.CENTER); // 消除字体锯齿 grayTextpaint.setFlags(Paint.ANTI_ALIAS_FLAG); } /*设置是哪一年*/ public void setYear(int year) { this.year=year; } public void setMonth(int month) { this.month=month; /*根据年、月获取 该月份的第一天是星期几*/ mWeekFirst1 = DateUtils.calWeek(year, month, 1); } public void setTotalDays(int daysByYearMonth) { this.mMonthdays=daysByYearMonth; } public void setdata(List<Integer> kuanggong, List<Integer> qiantui, List<Integer> zaotui, List<Integer> chiDao, List<Integer> weiQianDao) { this.mKuanggong=kuanggong; this.mQiantui=qiantui; this.mZaotui=zaotui; this.mChiDao=chiDao; this.mWeiQianDao=weiQianDao; /*设置数据后,重新绘制图形*/ postInvalidate(); } /* private void initdata() { mKuanggong = Arrays.asList(10, 20, 12); mQiantui = Arrays.asList(6); mZaotui = Arrays.asList(7); mChiDao = Arrays.asList(9); mWeiQianDao = Arrays.asList(13); }*/ }
Activity代码:
package com.eben.zhukeyunfu.Activity.textexampleActivity; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.AnimationUtils; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import com.eben.zhukeyunfu.Activity.utils.DateUtils; import com.eben.zhukeyunfu.Activity.view.MyCalendar; import com.eben.zhukeyunfu.R; import com.google.android.gms.appindexing.Action; import com.google.android.gms.appindexing.AppIndex; import com.google.android.gms.appindexing.Thing; import com.google.android.gms.common.api.GoogleApiClient; import java.util.Arrays; import java.util.List; import static com.eben.zhukeyunfu.R.anim.slide_left_in; import static com.eben.zhukeyunfu.R.anim.slide_right_out; /* * @项目名: Zhukeyunfu * @包名: com.eben.zhukeyunfu.Activity.textexampleActivity * @文件名: HeartActivity * @创建者: Administrator * @创建时间: 2017/2/13 15:28 * @描述: TODO */ public class KaoQinActivity extends AppCompatActivity { private static final String TAG = "FootActivity"; private int mYear; private int mMonth; private List<Integer> mKuanggong; private List<Integer> mQiantui; private List<Integer> mZaotui; private List<Integer> mChiDao; private List<Integer> mWeiQianDao; private TextView mSwitchMdoe; private AnimationSet mAnimationSet1; private AnimationSet mAnimationSet2; private AnimationSet mAnimationSet3; private AnimationSet mAnimationSet4; private boolean islist = true; /** * ATTENTION: This was auto-generated to implement the App Indexing API. * See https://g.co/AppIndexing/AndroidStudio for more information. */ private GoogleApiClient mClient; private LinearLayout mCalendar_mode; private ListView mList_mode; private int mDays1Month; private Myadapter mMyadapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); changeColor(); setContentView(R.layout.kaoqin); //初始化actionbar //initactionbar(); //初始化布局 //改变手机状态栏颜色 initview(); initanimator(); initlistener(); // ATTENTION: This was auto-generated to implement the App Indexing API. // See https://g.co/AppIndexing/AndroidStudio for more information. mClient = new GoogleApiClient.Builder(this).addApi(AppIndex.API) .build(); } private void initanimator() { mAnimationSet1 = (AnimationSet) AnimationUtils.loadAnimation(KaoQinActivity.this, R.anim.slide_left_in); mAnimationSet2 = (AnimationSet) AnimationUtils.loadAnimation(KaoQinActivity.this, R.anim.slide_left_out); mAnimationSet3 = (AnimationSet) AnimationUtils.loadAnimation(KaoQinActivity.this, R.anim.slide_right_in); mAnimationSet4 = (AnimationSet) AnimationUtils.loadAnimation(KaoQinActivity.this, R.anim.slide_right_out); /*四个动画的监听*/ mAnimationSet1.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } }); mAnimationSet2.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { mCalendar_mode.setVisibility(View.GONE); } @Override public void onAnimationRepeat(Animation animation) { } }); mAnimationSet3.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } }); mAnimationSet4.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { mList_mode.setVisibility(View.GONE); } @Override public void onAnimationRepeat(Animation animation) { } }); } private void initlistener() { /*切换视图*/ mSwitchMdoe.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /*开始切换模式,执行动画*/ if (islist == true) { mSwitchMdoe.setText("考勤"); mCalendar_mode.startAnimation(mAnimationSet2); mList_mode.startAnimation(mAnimationSet3); mList_mode.setVisibility(View.VISIBLE); islist=false; }else { mSwitchMdoe.setText("工资"); mCalendar_mode.startAnimation(mAnimationSet1); mList_mode.startAnimation(mAnimationSet4); mCalendar_mode.setVisibility(View.VISIBLE); islist=true; } } }); mMyadapter = new Myadapter(); mList_mode.setAdapter(mMyadapter); } private void initview() { ImageView mBack = (ImageView) findViewById(R.id.back_heart); mBack.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); overridePendingTransition(slide_left_in, slide_right_out); } }); /*设置日期*/ final TextView date = (TextView) findViewById(R.id.date); /*获取当前的月份及年份*/ mYear = DateUtils.getYear(); mMonth = DateUtils.getMonth(); date.setText(mYear + "年" + mMonth + "月"); /**/ final MyCalendar myCalendar = (MyCalendar) findViewById(R.id.myCalendar); /*设置日期*/ myCalendar.setYear(mYear); myCalendar.setMonth(mMonth); mKuanggong = Arrays.asList(10, 20, 12); mQiantui = Arrays.asList(6); mZaotui = Arrays.asList(7); mChiDao = Arrays.asList(9); mWeiQianDao = Arrays.asList(13); /*根据年和月获取天数*/ mDays1Month = DateUtils.getDaysByYearMonth(mYear, mMonth); myCalendar.setTotalDays(mDays1Month); myCalendar.setdata(mKuanggong, mQiantui, mZaotui, mChiDao, mWeiQianDao); /*查看下一月的数据*/ ImageView addMonth = (ImageView) findViewById(R.id.addMonth); addMonth.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mMonth++; if (mMonth == 13) { mMonth = 1; mYear++; } date.setText(mYear + "年" + mMonth + "月"); myCalendar.setYear(mYear); myCalendar.setMonth(mMonth); /*根据年和月获取天数*/ myCalendar.setTotalDays(DateUtils.getDaysByYearMonth(mYear, mMonth)); myCalendar.setdata(null, null, null, null, null); mMyadapter.notifyDataSetChanged(); } }); /*查看前一月的数据*/ ImageView decreaseMonth = (ImageView) findViewById(R.id.decreaseMonth); decreaseMonth.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mMonth--; if (mMonth == 0) { mMonth = 12; mYear--; } date.setText(mYear + "年" + mMonth + "月"); myCalendar.setYear(mYear); myCalendar.setMonth(mMonth); /*根据年和月获取天数*/ myCalendar.setTotalDays(DateUtils.getDaysByYearMonth(mYear, mMonth)); if (mMonth % 4 == 0) { myCalendar.setdata(mKuanggong, mQiantui, mZaotui, mChiDao, mWeiQianDao); } else { myCalendar.setdata(null, null, null, null, null); } mMyadapter.notifyDataSetChanged(); } }); /*切换视图*/ mSwitchMdoe = (TextView) findViewById(R.id.switch_mdoe); /*日历模式view*/ mCalendar_mode = (LinearLayout) findViewById(R.id.calendar_mode); /*列表模式*/ mList_mode = (ListView) findViewById(R.id.list_mode); } private void changeColor() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // View decorView = getWindow().getDecorView(); // int visibility = View.SYSTEM_UI_FLAG_FULLSCREEN;// 全屏设置 // int visibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;// 表示允许应用的主题内容占用状态栏的空间 // decorView.setSystemUiVisibility(visibility); getWindow().setStatusBarColor(getResources().getColor(R.color.black));// 通知栏颜色 } } //处理后退键的情况 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { this.finish(); //finish当前activity overridePendingTransition(slide_left_in, slide_right_out); return true; } return super.onKeyDown(keyCode, event); } /** * ATTENTION: This was auto-generated to implement the App Indexing API. * See https://g.co/AppIndexing/AndroidStudio for more information. */ public Action getIndexApiAction() { Thing object = new Thing.Builder().setName("KaoQin Page") // TODO: Define a title for the content shown. // TODO: Make sure this auto-generated URL is correct. .setUrl(Uri.parse("http://[ENTER-YOUR-URL-HERE]")) .build(); return new Action.Builder(Action.TYPE_VIEW).setObject(object) .setActionStatus(Action.STATUS_TYPE_COMPLETED) .build(); } @Override public void onStart() { super.onStart(); // ATTENTION: This was auto-generated to implement the App Indexing API. // See https://g.co/AppIndexing/AndroidStudio for more information. mClient.connect(); AppIndex.AppIndexApi.start(mClient, getIndexApiAction()); } @Override public void onStop() { super.onStop(); // ATTENTION: This was auto-generated to implement the App Indexing API. // See https://g.co/AppIndexing/AndroidStudio for more information. AppIndex.AppIndexApi.end(mClient, getIndexApiAction()); mClient.disconnect(); } class Myadapter extends BaseAdapter{ @Override public int getCount() { mDays1Month = DateUtils.getDaysByYearMonth(mYear, mMonth); if (mDays1Month>0){ return mDays1Month; } return 0; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder=null; if (holder==null){ holder=new ViewHolder(); convertView=View.inflate(KaoQinActivity.this,R.layout.listitem_kaoqin,null); holder.mTextView= (TextView) convertView.findViewById(R.id.datalist); } holder.mTextView.setText(mMonth+"月"+(position+1)+"日"); return convertView; } class ViewHolder{ TextView mTextView; } } }
当然代码有点多了,还有一些自定义的drawable什么的,都放在后面的压缩包里面,最后谢谢大家,供大家参考,这只是我自己的方案,没有参考别人的,获取网上有其他比我容易的方案,也请大家不要拍砖,我这个不是单独的demo,要使用这个需要自己把相关内容加进去才能使用。代码不简洁,也没有优化,请体谅。