赞
踩
工作这么久,第一次在CSDN上写技术博客,望大家多多支持;
本篇博文给大家分享一个考勤日历控件,这里有个需求:要求显示当前月的日期,左右可以切换月份来查看日期。可以通过不同的颜色表示每天的考勤状态; 这里我自定义了一个日历控件,大家以后可以根据自己的需求来修改代码。首先大家来看一下效果图:
一、为了让大家可以尽快的使用改控件,我首先会从如何调用该控件入手给大家讲解:
由于在效果上可以无限滑动,需要将我自定义的日历控件与ViewPager、Fragment控件配合使用,这样是得调用过程稍有复杂,请大家注意我的调用步骤:
1、将自定义DateViewN与DateWidgetDayCellN拷贝到自己的src下的包中,然后在将其使用到Fragment布局文件中,如下面代码,其中“com.selfview.calendar1“为我的src下的包目录,DateViewN为我自定义的柱状图View:
- /.........................../
- <com.selfview.calendar1.DateViewN
- android:id="@+id/dateview"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- /.........................../
2、创建一个Fragment类,调用上面建立的布局文件,下面我将关键代码贴出,并加以解释:
(1)在这个类中,我们应重点关注create(int pageNumber)这个方法,在ViewPager的滑动过程中,可以用ViewPager的页面编号,通过这个方法生成我们所需的Fragment;
(2)mPageNumber = getArguments().getInt(ARG_PAGE);// 获取当前页面编号;
(3)dateViewN.setShowDate(mPageNumber);//设置当前页面对应的自定义日历控件中的日期;
(4)dateViewN.setEntities(dateEntities);// 将数据集合放入自定义日历控件中
public static final String ARG_PAGE = "page";// key值 private int mPageNumber;// 当前页码 private DateViewN dateViewN;// 日历控件 private String currentMonth;// 当前月 private ArrayList<DateEntity> dateEntities;// 考勤数据集合 /.........................../ public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); /.........................../ mPageNumber = getArguments().getInt(ARG_PAGE);// 获取当前页面编号 } /.........................../ // 创建ItemFragmentDate通过ViewPager的页面编号 public static Fragment create(int pageNumber) { ItemFragmentDate fragment = new ItemFragmentDate(); Bundle args = new Bundle(); args.putInt(ARG_PAGE, pageNumber); fragment.setArguments(args); return fragment; } public ItemFragmentDate() { } /.........................../ dateViewN = (DateViewN) rootView.findViewById(R.id.dateview);// 初始日历控件 dateViewN.setShowDate(mPageNumber);//设置当前页面对应的自定义日历控件中的日期 currentMonth = dateViewN.getDateEntity().year + "-" + getAddZero(dateViewN.getDateEntity().month + "");//获取当前页面对应的年月 getDateEntityToNet(currentMonth);//通过当前月向网络获取数据 /.........................../ dateViewN.setEntities(dateEntities);// 将数据集合放入自定义日历控件中
3、自定义ViewPager适配器:
其中我定义ViewPager的总页面为1000页,对我的考勤日历来说已经足够,大家使用时可根据自己的需求来定
public class CalendarAdapter extends FragmentStatePagerAdapter { private final int ALL_PAGE_NUM = DateViewN.PAER_NUM * 2;// 设置页面总数 public CalendarAdapter(FragmentManager fm) { super(fm); // TODO Auto-generated constructor stub } @Override public Fragment getItem(int arg0) { return ItemFragmentDate.create(arg0);// 根据传入的页面当前页面编号生成ItemFragmentDate对象碎片 } @Override public int getCount() { // TODO Auto-generated method stub return ALL_PAGE_NUM; } }
4、配置主页面布局,也就是调用一个ViewPager:
/.........................../ <android.support.v4.view.ViewPager android:id="@+id/viewpager_calender" android:layout_width="fill_parent" android:layout_height="0dip" android:layout_gravity="center" android:layout_weight="1" > </android.support.v4.view.ViewPager> /.........................../5、编写主页面代码:
/.........................../ private ViewPager viewpager_calender;// 左右滑动控件 private CalendarAdapter calendarAdapter;// ViewPager的适配器 private int startPageNum = DateViewN.PAER_NUM;// 将当前页面设置成第500个页面,往前可以滑动499次,499个月,对应考勤而言已经足够 /.........................../ viewpager_calender = (ViewPager) findViewById(R.id.viewpager_calender); calendarAdapter = new CalendarAdapter(getSupportFragmentManager()); viewpager_calender.setAdapter(calendarAdapter);// 设置ViewPager适配器 viewpager_calender.setCurrentItem(currentPageNum); /.........................../
二、上面讲述了如何调用日历控件,下面我来讲一下如何自定义日历控件:
1、根据考勤需求先建立一个DateEntity对象,该对象中记录了每一天的考勤状态,以下为该对象属性:
private String Date;//日期 2016-11-25
private String startTime;//上班时间 08:00
private String endTime;//下班时间 20:00
private String overWorkDate;//加班时段 18:00-20:00
private String outWorkDate;//出差时段 16:00-17:00
private String leaveDate;//请假时段 12:00-15:00
private String mark;//考勤说明
public int year;//日期分解年 2016
public int month;//日期分解月 11
public int day;//日期分解日 25
public int week;//日期分解星期几
public boolean isToday;//当前日期是否为今天
private boolean isLate;//是否迟到
private boolean isWork;//是否工作日
private boolean isEarly;//是否早退
private boolean isNormal;//状态是否正常
2、自定义单独的一个Item类DateWidgetDayCellN,及每一天,将各个状态(如:迟到/早退、加班、出差、请假等)使用不同的布尔值来定义,根据布尔值来绘制各个颜色:
(1)定义类中属性:
private int fTextSize; // 字体大小
// 基本元素
private final int margin = 6;// 选中时左右两边的边距
private OnItemClick itemClick = null;//点击监听
private Paint pt = new Paint();//绘制字体画笔
private Paint linePaint = new Paint();//划线
private Paint circlePaint = new Paint();//画圆
private int radius;//圆半径
private RectF rect = new RectF();//单元格
private String sDate = "";//当前日
private int iDateYear = 0;
private int iDateMonth = 0;
private int iDateDay = 0;
private String weekString;//星期几
private int row;//在一页日历中,当前日在第几行
// 布尔变量
private boolean bSelected = false;// 是否为被点击/选择状态
private boolean bCurrentMonth = false;// 是否当月
private boolean bToday = false;// 是否今天
private boolean bHoliday = false;// 是否假期
private boolean bLeave = false;// 是否休假
private boolean bOut = false;// 是否休假
private boolean bOverTime = false;// 是否加班
private boolean bLate = false;// 是否迟到
private String startTime;//上班时间
private String endTime;//下班时间
private String overWorkDate;//加班时段
private String outWorkDate;//出差时段
private String leaveDate;//请假时段
private String mark;//考勤说明
private float mDownX;//按下位置的X值
private float mDownY;//按下位置的Y值
private int touchSlop;// 滑动最小距离,防止误点击,只有滑动距离大于touchSlop才认为是点击
(2)构造函数与数据传入方法
// px与dip转换工具类,此方法可根据屏幕尺寸不同将相同的dip值转换成不同的px值,已达到适配不同屏幕的效果 public int dip2px(float dipValue) { float scale = getResources().getDisplayMetrics().density; return (int) (dipValue * scale + 0.5f); } // 构造函数 public DateWidgetDayCellN(Context context, int iWidth, int iHeight, int row) { super(context); this.row = row; // 以下三行作用,设置view可点击不会占用父布局焦点 setClickable(true); setFocusable(false); setFocusableInTouchMode(false); setLayoutParams(new LayoutParams(iWidth, iHeight));// 设置控件大小 touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();// 设置最小滑动距离 fTextSize = dip2px(15); radius = (Math.min(iHeight, iWidth) - dip2px(20)) / 2;// 设置圆半径 } // 设置变量值 public void setData(int iYear, int iMonth, int iDay, Boolean bToday, boolean bCurrentMonth, boolean bLeave, boolean bOut, boolean bHoliday, boolean bOverTime, boolean bLate, int week, String startTime, String endTime, String overWorkDate, String outWorkDate, String leaveDate, String mark) { iDateYear = iYear; iDateMonth = iMonth; iDateDay = iDay; this.startTime = startTime; this.endTime = endTime; this.overWorkDate = overWorkDate; this.outWorkDate = outWorkDate; this.leaveDate = leaveDate; this.mark = mark; this.sDate = Integer.toString(iDateDay); this.bCurrentMonth = bCurrentMonth; this.bToday = bToday; this.bLate = bLate; this.bLeave = bLeave; this.bOut = bOut; this.bOverTime = bOverTime; this.bHoliday = bHoliday; if (week == 0) { weekString = "星期日"; } else if (week == 1) { weekString = "星期一"; } else if (week == 2) { weekString = "星期二"; } else if (week == 3) { weekString = "星期三"; } else if (week == 4) { weekString = "星期四"; } else if (week == 5) { weekString = "星期五"; } else if (week == 6) { weekString = "星期六"; } invalidate();//绘制图形 }(3)绘制图形:
// 重载绘制方法 @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); rect.set(0, 0, this.getWidth(), this.getHeight());// 设置单元格大小 // 设置画笔属性 linePaint.setAntiAlias(true); linePaint.setStrokeWidth(dip2px(1)); linePaint.setColor(getResources().getColor(R.color.gray_calender_line)); // 绘制底线,选中时不绘制 if (!bSelected) { canvas.drawLine(0, this.getHeight(), this.getWidth(), this.getHeight(), linePaint); } drawDayView(canvas);// 绘制日历方格,包括各个属性状态 drawDayNumber(canvas);// 绘制日历中的数字 }
(3.1)绘制日历方格,包括各个属性状态:
由于绘制方格的这一过程比较复杂,特别是在该方格为选中状态时,所以为了大家有个清晰的认识,首先我将绘制选中状态的思路先用例图说明一下,如下图示:
上图分为6个步骤绘制选中时的灰色背景:
1步:在控件中绘制一个矩形,其与父控件的左右上边距是相当的;
2步:在绘制的矩形中,绘制一个半椭圆,背景为选中时的背景;
3步:绘制下部矩形,背景为选中时的背景;
4步:绘制左右正方形,背景为选中时的背景;
5步:绘制圆弧,背景为白色;
6步:将左右正方形中多余的选中背景改为白色。
// 绘制日历方格 private void drawDayView(Canvas canvas) { int realMargin = dip2px(margin); float h = this.getHeight(); if (bSelected) { linePaint.setColor(getResources().getColor(R.color.grey_backgrond));// 设置画笔为灰色 RectF oval = new RectF(realMargin, realMargin, this.getWidth() - realMargin, h);// 在cell中设置一个选中范围内的矩形 canvas.drawArc(oval, 180, 180, true, linePaint);// 绘制顶部圆弧 // 参数意义从180度开始,画180度,顺时针绘制 canvas.drawRect(dip2px(margin), (h - dip2px(margin)) / 2 + realMargin, this.getWidth() - realMargin, h, linePaint);// 画底部矩形 canvas.drawRect(0, h - realMargin, realMargin, h, linePaint);// 绘制左边底部小矩形,背景灰色 canvas.drawRect(this.getWidth() - realMargin, h - realMargin, this.getWidth(), h, linePaint);// 绘制右边边底部小矩形,背景灰色 linePaint.setColor(Color.WHITE);// 设置画笔为白色 oval = new RectF(0, h - realMargin, realMargin, h); canvas.drawArc(oval, 0, 90, true, linePaint);// 左边底部小矩形 绘制圆弧 canvas.drawRect(0, h - realMargin, realMargin / 2, h, linePaint); canvas.drawRect(0, h - realMargin, realMargin, h - realMargin / 2, linePaint);// 将左边底部小矩形剩余灰色部分绘制成白色 oval = new RectF(this.getWidth() - realMargin, h - realMargin, this.getWidth(), h); canvas.drawArc(oval, 90, 90, true, linePaint);// 右边底部小矩形 绘制圆弧 canvas.drawRect(this.getWidth() - realMargin, h - realMargin, this.getWidth(), h - realMargin / 2, linePaint); canvas.drawRect(this.getWidth() - realMargin / 2, h - realMargin, this.getWidth(), h, linePaint);// 将右边底部小矩形剩余灰色部分绘制成白色 linePaint.setColor(getResources().getColor(R.color.grey_backgrond));// 将选中时将底部线颜色绘制为选中背景颜色 canvas.drawLine(0, this.getHeight(), this.getWidth(), this.getHeight(), linePaint); } circlePaint.setStyle(Paint.Style.FILL); circlePaint.setAntiAlias(true); RectF oval = new RectF(this.getWidth() / 2 - radius, this.getHeight() / 2 - radius, this.getWidth() / 2 + radius, this.getHeight() / 2 + radius);// 绘制状态背景圆 for (int i = 0; i < getColorBkg().size(); i++) { circlePaint.setColor(getColorBkg().get(i));// 根据状态的多少,绘制不同颜色和角度的扇形 canvas.drawArc(oval, (i * 360) / getColorBkg().size(), 360 / getColorBkg().size(), true, circlePaint); } } // 根据条件返回不同颜色值 private ArrayList<Integer> getColorBkg() { ArrayList<Integer> integers = new ArrayList<Integer>(); if (bSelected) { integers.add(Color.RED); return integers; } if (bLate) integers.add(Color.parseColor("#FF9595")); if (bOverTime) { integers.add(Color.parseColor("#F7AC1A")); } if (bOut) integers.add(Color.parseColor("#2CCCBB")); if (bLeave) integers.add(Color.parseColor("#1FB9ED")); if (!bLate && !bOverTime && !bOut && !bLeave) integers.add(Color.WHITE); return integers; }(4)设置点击事件,建立监听接口:
public interface OnItemClick {//设置监听接口 public void OnClick(DateWidgetDayCellN item);//监听方法 } public void setItemClick(OnItemClick itemClick) { this.itemClick = itemClick; } public void doItemClick() { if (itemClick != null) itemClick.OnClick(this); //点击后会获取到这个View,包括它所有的状态 } // 点击事件 @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mDownX = event.getX(); mDownY = event.getY(); break; case MotionEvent.ACTION_UP: float disX = event.getX() - mDownX; float disY = event.getY() - mDownY; if (Math.abs(disX) < touchSlop && Math.abs(disY) < touchSlop) { // setSelected(true); doItemClick(); } break; } return true; }
3、将DateWidgetDayCellN组合起来,形成DateViewN类,首先,我先讲将我的整体思路向大家介绍一下:
(1)如下图一所示,一个月最多占的行列为6行7列;所以我会创建6个LinearLayout,而这6个LinearLayout中会包含7个DateWidgetDayCellN对象;
(2)由于每点击一个日期单元格时,会有关于该天的考勤说明展现,就会展现在该日期行的下方,假设说明行都展现完全的话,就会如图二所示,故我会在每个行下面在加上一个LinearLayout,形成一个12X7的布局,如图二所示;
(3)布局完控件后,再根据当月数据对多余的控件进行隐藏和移除即可。
(图1) (图二)
4、DateViewN类代码说明:
(1)各个属性的定义:
public static final int PAER_NUM = 500;// 设置ViewPager页数 private int width;// 行宽度 private int height;// 日历行高度 private int cellWidth;// DateWidgetDayCellN宽度 private int cellHeight;// DateWidgetDayCellN高度 private Context context; private LinearLayout mLinearLayoutContent = null;// 整个日历控件的父LinearLayout private View[] views;// 考勤说明行View数组 private int iRow;// 行标 private ScrollView mScrollView = null;// 包含mLinearLayoutContent,使其可上下滑动 private ArrayList<DateWidgetDayCellN> mCalendarCells = new ArrayList<DateWidgetDayCellN>();// DateWidgetDayCellN集合 private DateEntity mShowDate;// 当前年月 private ArrayList<DateEntity> entities;// 所传入数据集合 private ArrayList<DateEntity> currentEntities;// 当前月的数据集合 private MyGridView mygridview_item;// 说明行中的GridView private DateGridViewAdapter viewAdapter;// GridView的适配器 private ArrayList<DateState> dateStates = null;// 说明行中所展示的数据集合 private boolean isExpansion;// 判断说明行是否展开(2)构造方法:
// 构造函数 public DateViewN(Context context) { this(context, null); } // 构造函数 public DateViewN(Context context, AttributeSet attrs) { this(context, attrs, 0); } // 构造函数 public DateViewN(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.context = context; this.mShowDate = new DateEntity();// 第一次进入设置当前日期为系统日期 this.entities = new ArrayList<DateEntity>(); // 以下三行是设置整个View为LinearLayout布局,且为垂直布局,背景为白色 new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); this.setOrientation(LinearLayout.VERTICAL); this.setBackgroundColor(Color.rgb(255, 255, 255)); // 行宽度为屏幕宽度 width = getResources().getDisplayMetrics().widthPixels; // 行高为屏幕高度*27/60 height = getResources().getDisplayMetrics().heightPixels * 27 / 60; // 以下六行为创建一个ScrollView并添加到View中 mScrollView = new ScrollView(context); mScrollView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); mScrollView.setVerticalScrollBarEnabled(false); mScrollView.setVerticalFadingEdgeEnabled(false); mScrollView.setHorizontalFadingEdgeEnabled(false); addView(mScrollView); // 以下四行为创建一个LinearLayout并添加到mScrollView中 mLinearLayoutContent = new LinearLayout(context); mLinearLayoutContent.setLayoutParams(new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); mLinearLayoutContent.setOrientation(LinearLayout.VERTICAL); mScrollView.addView(mLinearLayoutContent); cellWidth = width / 7;// 单个DateWidgetDayCellN宽度 cellHeight = height / 6;// 单个DateWidgetDayCellN高度 initRow();// 初始布局即12X7的布局 calculateDate();// 通过数据对初始化布局进行,数据的展现,多余控件的隐藏或移除 }(3)初始布局即12X7的布局
// 初始布局即12X7的布局 public void initRow() { isExpansion = false;// 默认说明行为不展开 mLinearLayoutContent.removeAllViews();// 移除父布局中所有元素 mCalendarCells.clear();// 清除mCalendarCells集合 views = new View[6];// 设置说明行views数组 for (iRow = 0; iRow < 6; iRow++) { LinearLayout mLinearLayoutRow = new LinearLayout(context); mLinearLayoutRow.setLayoutParams(new LayoutParams(width, LayoutParams.WRAP_CONTENT)); mLinearLayoutRow.setOrientation(LinearLayout.HORIZONTAL); // 以上为新建一个日历行 for (int iDay = 0; iDay < 7; iDay++) {// 一行有7个DateWidgetDayCellN DateWidgetDayCellN dayCell = new DateWidgetDayCellN(context, cellWidth, cellHeight, iRow);// 新建DateWidgetDayCellN mCalendarCells.add(dayCell);// 将新建的DateWidgetDayCellN放入mCalendarCells集合中 dayCell.setItemClick(new OnItemClick() {// 设置DateWidgetDayCellN点击事件监听 @Override public void OnClick(DateWidgetDayCellN item) { if (item.isbSelected()) {// 若被DateWidgetDayCellN已经被选中,点击后则为未选中状态,且说明行不展示 for (DateWidgetDayCellN cell : mCalendarCells) { cell.setSelected(false); } isExpansion = false; } else {// 若被DateWidgetDayCellN未被选中,点击后则为选中状态,且说明行展示,除了这个item,mCalendarCells所有的都为未选中态, for (DateWidgetDayCellN cell : mCalendarCells) { cell.setSelected(false); } item.setSelected(true); isExpansion = true; } String s = item.getDate(); if (isExpansion) {// 根据isExpansion状态来显示或隐藏说明行 if (item.isbSelected()) { switch (item.getRow()) { case 0: setTextVisibilityNew(0, s); break; case 1: setTextVisibilityNew(1, s); break; case 2: setTextVisibilityNew(2, s); break; case 3: setTextVisibilityNew(3, s); break; case 4: setTextVisibilityNew(4, s); break; case 5: setTextVisibilityNew(5, s); break; } } } else { closeTextVisibility(); } } }); mLinearLayoutRow.addView(dayCell);// 将dayCell加入日历行中 } // 根据航标来设置说明行 views[iRow] = View.inflate(context, R.layout.calender_item_new, null); views[iRow].setLayoutParams(new LayoutParams(width, LayoutParams.WRAP_CONTENT)); views[iRow].setBackgroundColor(Color.GRAY); views[iRow].setVisibility(View.GONE); mLinearLayoutContent.addView(mLinearLayoutRow);// 将日历行添加到父布局中 mLinearLayoutContent.addView(views[iRow]);// 将说明行添加到父布局中 } }(4)、当前日期设置与数据传入接口:
// 根据ViewPager页面编号来设置当前日期 public void setShowDate(int i) { i = i - PAER_NUM; if (i > 0) { for (int j = 0; j < i; j++) { if (mShowDate.month == 12) { mShowDate.month = 1; mShowDate.year += 1; } else { mShowDate.month += 1; } } } if (i < 0) { // 向左滑动 for (int j = 0; j < Math.abs(i); i++) { if (mShowDate.month == 1) { mShowDate.month = 12; mShowDate.year -= 1; } else { mShowDate.month -= 1; } } } update(); } // 更新UI public void update() { initRow(); calculateDate(); } // 设置数据入口 public void setEntities(ArrayList<DateEntity> entities) { if (entities != null) this.entities = entities; else this.entities = new ArrayList<DateEntity>(); update(); }(5)根据当前日期与传入数据对布局进行筛选(及对多余控件进行隐藏或移除):
// 通过数据对初始化布局进行,数据的展现,多余控件的隐藏或移除 private void calculateDate() { if (currentEntities != null) currentEntities.clear(); currentEntities = getCurrentMonth(entities);// 当前月数据 int currentMonthDays = getMonthDays(mShowDate.year, mShowDate.month);// 当前月天数 int firstDayWeek = getWeekDayFromDate(mShowDate.year, mShowDate.month);// 获取随意的年月的第一天是星期几0日,1一,..6六 int monthDay = getCurrentMonthDay();// 手机系统对应的今天的日期 boolean isCurrentMonth = false; if (isCurrentMonth(mShowDate)) {// 是否为手机系统对应的年月 isCurrentMonth = true; } int day = 0; boolean flag = false; for (int i = 0; i < mCalendarCells.size(); i++) {// 对mCalendarCells中的DateWidgetDayCellN进行数据传入操作 flag = false; // firstDayWeek值可能为0,1,2,3,4,5,6 if (i >= firstDayWeek && i < firstDayWeek + currentMonthDays) {// 判断当前月在mCalendarCells中对应的DateWidgetDayCellN day++;// day从1-当前月天结束; for (DateEntity d : currentEntities) { if (d.day == day) {// 对currentEntities记录中存在的天数,进行数据传入操作 mCalendarCells.get(i).setData(d.year, d.month, d.day, d.isToday, true, isLeave(d), isOut(d), !d.isWork(), isOverWork(d), isLateOrEarly(d), d.week, d.getStartTime(), d.getEndTime(), d.getOverWorkDate(), d.getOutWorkDate(), d.getLeaveDate(), d.getMark()); flag = true; if (d.isToday) {// 判断日期是否为手机系统中的今天,如果是默认为选中状态,说明行显示 mCalendarCells.get(i).setSelected(true);// 默认为选中状态 isExpansion = true; String s = mCalendarCells.get(i).getDate(); if (isExpansion) {// 说明行显示 if (mCalendarCells.get(i).isbSelected()) { switch (mCalendarCells.get(i).getRow()) { case 0: setTextVisibilityNew(0, s); break; case 1: setTextVisibilityNew(1, s); break; case 2: setTextVisibilityNew(2, s); break; case 3: setTextVisibilityNew(3, s); break; case 4: setTextVisibilityNew(4, s); break; case 5: setTextVisibilityNew(5, s); break; } } } else { closeTextVisibility();// 屏蔽所有说明行 } } break; } } if (!flag) {// 判断如果日期在currentEntities记录中没有找到对应的数据时,进行的操作 DateEntity date = DateEntity.modifiDayForObject(mShowDate, day); // 设置年月日 if (i == 0) { date.week = i; } else { date.week = i % 7; }// 设置星期几 if (isCurrentMonth && (day == monthDay)) {// 判断日期是否为手机系统中的今天,如果是默认为选中状态,说明行显示 mCalendarCells.get(i).setData(date.year, date.month, date.day, true, true, false, false, false, false, false, date.week, null, null, null, null, null, null); mCalendarCells.get(i).setSelected(true);// 默认为选中状态 isExpansion = true; String s = mCalendarCells.get(i).getDate(); if (isExpansion) {// 说明行显示 if (mCalendarCells.get(i).isbSelected()) { switch (mCalendarCells.get(i).getRow()) { case 0: setTextVisibilityNew(0, s); break; case 1: setTextVisibilityNew(1, s); break; case 2: setTextVisibilityNew(2, s); break; case 3: setTextVisibilityNew(3, s); break; case 4: setTextVisibilityNew(4, s); break; case 5: setTextVisibilityNew(5, s); break; } } } else { closeTextVisibility();// 屏蔽所有说明行 } } else {//判断如果日期在currentEntities记录中没有找到对应的数据时,进行数据传入 mCalendarCells.get(i).setData(date.year, date.month, date.day, false, true, false, false, false, false, false, date.week, null, null, null, null, null, null); } } } else if (i < firstDayWeek) {// 如果i小于firstDayWeek,则说明第一行从0(星期日)到firstDayWeek-1位当前月的上个月,将上个月的DateWidgetDayCellN隐藏 mCalendarCells.get(i).setVisibility(View.INVISIBLE); } else if (i >= firstDayWeek + currentMonthDays) {// 如果i >= // firstDayWeek // + // currentMonthDays,这说明后面的控件为当前月的下个月,可以移除 mCalendarCells.get(i).setVisibility(View.GONE); } } }这样我们就完成了整个无限滑动的考勤日历控件了,大家可以根据自己的需求进行更改,获取自己想要的效果,全部代码我稍后会附上。
由于这个控件是我很久之前写的,还有很多可以改进的空间,感觉有些思路大家还是可以借鉴一下,故此先写上一篇;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。