工作这么久,第一次在CSDN上写技术博客,望大家多多支持;

本篇博文给大家分享一个考勤日历控件,这里有个需求:要求显示当前月的日期,左右可以切换月份来查看日期。可以通过不同的颜色表示每天的考勤状态; 这里我自定义了一个日历控件,大家以后可以根据自己的需求来修改代码。首先大家来看一下效果图:

             

一、为了让大家可以尽快的使用改控件,我首先会从如何调用该控件入手给大家讲解:

      由于在效果上可以无限滑动,需要将我自定义的日历控件与ViewPager、Fragment控件配合使用,这样是得调用过程稍有复杂,请大家注意我的调用步骤:

      1、将自定义DateViewN与DateWidgetDayCellN拷贝到自己的src下的包中,然后在将其使用到Fragment布局文件中,如下面代码,其中“com.selfview.calendar1“为我的src下的包目录,DateViewN为我自定义的柱状图View:

   
 /.........................../ <com.selfview.calendar1.DateViewNandroid: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 stubsuper.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}@Overridepublic Fragment getItem(int arg0) {return ItemFragmentDate.create(arg0);// 根据传入的页面当前页面编号生成ItemFragmentDate对象碎片}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn ALL_PAGE_NUM;}
}

4、配置主页面布局,也就是调用一个ViewPager:

 /.........................../
<android.support.v4.view.ViewPagerandroid: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-25private String startTime;//上班时间 08:00private String endTime;//下班时间 20:00private String overWorkDate;//加班时段 18:00-20:00private String outWorkDate;//出差时段 16:00-17:00private String leaveDate;//请假时段  12:00-15:00private String mark;//考勤说明 public int year;//日期分解年 2016public int month;//日期分解月 11public int day;//日期分解日 25public 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)绘制图形:

  // 重载绘制方法@Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.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,包括它所有的状态}// 点击事件@Overridepublic 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;// 整个日历控件的父LinearLayoutprivate 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;// 说明行中的GridViewprivate 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/60height = 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个DateWidgetDayCellNDateWidgetDayCellN dayCell = new DateWidgetDayCellN(context,cellWidth, cellHeight, iRow);// 新建DateWidgetDayCellNmCalendarCells.add(dayCell);// 将新建的DateWidgetDayCellN放入mCalendarCells集合中dayCell.setItemClick(new OnItemClick() {// 设置DateWidgetDayCellN点击事件监听@Overridepublic 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();}// 更新UIpublic void update() {initRow();calculateDate();}// 设置数据入口public void setEntities(ArrayList<DateEntity> entities) {if (entities != null)this.entities = entities;elsethis.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,6if (i >= firstDayWeek && i < firstDayWeek + currentMonthDays) {// 判断当前月在mCalendarCells中对应的DateWidgetDayCellNday++;// 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);}}}

这样我们就完成了整个无限滑动的考勤日历控件了,大家可以根据自己的需求进行更改,获取自己想要的效果,全部代码我稍后会附上。

由于这个控件是我很久之前写的,还有很多可以改进的空间,感觉有些思路大家还是可以借鉴一下,故此先写上一篇;

Android考勤日历控件相关推荐

  1. 记一次Android第三方日历控件CalendarView的使用

    一.文章背景 用过两个日历控件的库,有用viewpager实现的,也有用canvas实现的.在实际使用过程中,发现使用canvas实现的calendarView切换下一月和下一年这种操作时切换更流畅. ...

  2. Android自定义日历控件,自带农历节假日,已经开源,即取即用~

    关注本人的更多博客:http://www.cnblogs.com/liushilin/ 该自定义日历控件已经开源:github地址 可能不少的小伙伴都有看楼主昨天发的自定义日历控件,虽然实现功能不多, ...

  3. 自定义日历控android,Android 一个日历控件的实现小记

    先看几张动态的效果图吧! 这里主要记录一下在编写日历控件过程中一些主要的点: 一.主要功能 1.支持农历.节气.常用节假日 2.日期范围设置,默认支持的最大日期范围[1900.1~2049.12] 3 ...

  4. android自定义选年控件,Android精美日历控件CalendarView自定义使用完全解析

    项目github地址 此框架采用组合的方式,各个模块互相独立,可自由采用各种提供的控件组合,完全自定义自己需要的UI,周视图和月视图可通过简单自定义任意自由绘制,不怕美工提需求!!!下面教程将介绍如何 ...

  5. android美柚日历控件,仿美柚大姨妈日历

    [实例简介] 仿美柚月经显示在日历上,包括月经记录,月经预测,月经分析等功能 [实例截图] [核心代码] 6306a7a2-fa5a-4fa8-b376-199fbe2b9d21 └── 仿美柚大姨妈 ...

  6. 日历控件的android代码,Android日历控件PickTime代码实例

    Android日历控件PickTime代码实例 发布时间:2020-10-03 16:05:51 来源:脚本之家 阅读:86 作者:手撕高达的村长 最近做项目,需要设置用户的生日,所以做这样一个功能. ...

  7. android程序日历layout,Android使用GridLayout绘制自定义日历控件

    效果图 思路:就是先设置Gridlayout的行列数,然后往里面放置一定数目的自定义日历按钮控件,最后实现日历逻辑就可以了. 步骤: 第一步:自定义日历控件(初步) 第二步:实现自定义单个日期按钮控件 ...

  8. Android开发之如何实现日历控件

    我们大家都知道,在Android平台3.0中才新增了日历视图控件,可以显示网格状的日历内容,那么对于3.0以下的版本要使用日历控件只能借助第三方,目前用的最多的是CalendarView. 先简单介绍 ...

  9. android组合控件的焦点,撸一个简单的TV版焦点控制的日历控件

    1.效果 最近需求要一个遥控控制的日历控件,找了半天没找到轮子,就自己撸一个,先看效果图: 效果图.gif 2.XML属性,所有属性默认为效果图 calender_textSize:星期和日期的字体大 ...

最新文章

  1. Linux 操作系统原理 — 内存 — 页式管理、段式管理与段页式管理
  2. 未来CPU内核将更简单!
  3. 把别人的Tcl/Tk代码加入到Go语言里12 游戏5 画图案?
  4. 第一次接触正则表达式/^[A-Za-z_][A-Za-z0-9_]{5,15}$/
  5. 紫书 习题8-14 UVa 1616(二分+小数化分数+精度)
  6. bigdecimal不保留小数_为什么 0.1 + 0.2 = 0.3,原来你不知道
  7. 记一次Animator状态快速切换问题的解决
  8. pyhton2 and python3 生成随机数字、字母、符号字典(用于撞库测试/验证码等)
  9. arcgis制作空间变化图怎么做_Arcgis专题地图的编制
  10. linux信号量使用
  11. 超详细的Python安装和环境搭建教程
  12. 莫队算法学习笔记(一)——普通莫队
  13. python可以这样学读后感_《Python深度学习》读后感
  14. php 国际标准时间_关于时区:PHP date_default_timezone_set()东部标准时间(EST)
  15. SQLserver分离数据库
  16. 安卓上利用百度输入法提供的导入词库与个性短语,批量造词方便输入
  17. 电路方程的矩阵形式 c语言,电路方程的矩阵形式
  18. 深度神经网络和人工神经网络区别
  19. 高效采集互联网信息,用绿色版网页采集器
  20. phpyun 模板判断

热门文章

  1. 《Adobe Illustrator CS5中文版经典教程》—第0课0.8节 在Illustrator CS5中置入Photoshop图像...
  2. LeetCode 289 Game of Life(生命游戏)(Array)
  3. 网管不是无奈之中的替补职业
  4. 实现类似王者荣耀的战令功能
  5. 两个numpy的向量相乘并生成矩阵
  6. 服务器安装 centos 系统
  7. Vue作业(实现比较数字大小,实现导航栏)
  8. cat /proc/meminfo 详解
  9. 软件架构师应该知道的97件事(极致总结)
  10. JAVA 拍照 exif GPS_读取图片EXIF块中GPS信息,转换为高德地图API坐标