Android自定义日历控件
jopen
10年前
/** * 描述:自定义日历控件 * The Class CalendarView. * @author LiuZiWei * @date 2014-4-28 */ @SuppressLint("ViewConstructor") public class CalendarView extends LinearLayout { /** The context. */ private Context context; /** The m linear layout header. */ private LinearLayout mLinearLayoutHeader = null; /** The m linear layout content. */ private LinearLayout mLinearLayoutContent = null; /** The m calendar header. */ private CalendarHeader mCalendarHeader = null; /** The width. */ private int width = 200; /** 星期头的行高. */ private int headerHeight = MY.PHONEWIDTH/7-10; //行高 /** The row height. */ private int rowHeight = MY.PHONEWIDTH/7-10; //每个单元格的宽度 /** The cell width. */ private int cellWidth = MY.PHONEWIDTH/7; // 日期变量 /** The cal start date. */ public static Calendar calStartDate = Calendar.getInstance(); /** The cal today. */ private Calendar calToday = Calendar.getInstance(); /** The cal selected. */ private static Calendar calSelected = null; //累计日期 /** The cal calendar. */ private Calendar calCalendar = Calendar.getInstance(); /** The current month. */ private int currentMonth = 0; //本日历的第一个单元格的星期 /** The first day of week. */ private int firstDayOfWeek = Calendar.SUNDAY; //今天 private int Teday; private int ThisMonth; //得到需要特别显示的字的数据 private ArrayList<String> numberlist = new ArrayList<String>(); //当前显示的单元格 /** The m calendar cells. */ private static ArrayList<CalendarCell> mCalendarCells = new ArrayList<CalendarCell>(); /** The m on item click listener. */ private AbOnItemClickListener mOnItemClickListener; /** * Instantiates a new ab grid view. * * @param context the context */ public CalendarView(Context context,ArrayList<String> array) { this(context,array, null); } /** * Instantiates a new calendar view. * * @param context the context * @param attrs the attrs */ @SuppressWarnings("deprecation") public CalendarView(Context context,ArrayList<String> array,AttributeSet attrs) { super(context, attrs); this.context = context; this.numberlist=array; new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); this.setOrientation(LinearLayout.VERTICAL); this.setBackgroundColor(Color.rgb(255, 255, 255)); WindowManager wManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); Display display = wManager.getDefaultDisplay(); width = display.getWidth(); display.getHeight(); mLinearLayoutHeader = new LinearLayout(context); mLinearLayoutHeader.setLayoutParams(new LayoutParams(width,headerHeight)); mLinearLayoutHeader.setOrientation(LinearLayout.VERTICAL); mCalendarHeader = new CalendarHeader(context); mCalendarHeader.setLayoutParams(new LayoutParams(width,headerHeight)); mLinearLayoutHeader.addView(mCalendarHeader,new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); addView(mLinearLayoutHeader); mLinearLayoutContent = new LinearLayout(context); mLinearLayoutContent.setOrientation(LinearLayout.VERTICAL); addView(mLinearLayoutContent); cellWidth = (width-20)/7; //初始化选中今天 calSelected = Calendar.getInstance(); initRow(); initStartDateForMonth(); initCalendar(); } /** * Inits the row. */ public void initRow(){ mLinearLayoutContent.removeAllViews(); mCalendarCells.clear(); for (int iRow = 0; iRow <6; iRow++) { LinearLayout mLinearLayoutRow = new LinearLayout(context); mLinearLayoutRow.setLayoutParams(new LayoutParams(width,rowHeight)); mLinearLayoutRow.setOrientation(LinearLayout.HORIZONTAL); for (int iDay = 0; iDay < 7; iDay++) { CalendarCell dayCell = new CalendarCell(context,(iRow*7)+iDay,cellWidth,rowHeight); dayCell.setOnItemClickListener(mOnDayCellClick); mLinearLayoutRow.addView(dayCell); mCalendarCells.add(dayCell); } mLinearLayoutContent.addView(mLinearLayoutRow); } } /** * 描述:由于日历上的日期都是从周日开始的,计算第一个单元格的日期. */ private void initStartDateForMonth() { calStartDate.setTimeInMillis(calSelected.getTimeInMillis()); //获取当前的 currentMonth = calStartDate.get(Calendar.MONTH); calStartDate.get(Calendar.YEAR); calStartDate.set(Calendar.DAY_OF_MONTH, 1); calStartDate.set(Calendar.HOUR_OF_DAY, 0); calStartDate.set(Calendar.MINUTE, 0); calStartDate.set(Calendar.SECOND, 0); int iDay = 0; int iStartDay = firstDayOfWeek; if (iStartDay == Calendar.MONDAY) { iDay = calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.MONDAY; if (iDay < 0) iDay = 6; } if (iStartDay == Calendar.SUNDAY) { iDay = calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY; if (iDay < 0) iDay = 6; } calStartDate.add(Calendar.DAY_OF_WEEK, -iDay); } /** * 描述:更新日历. */ private void updateCalendar() { final boolean bIsSelection = (calSelected.getTimeInMillis() != 0); final int iSelectedYear = calSelected.get(Calendar.YEAR); final int iSelectedMonth = calSelected.get(Calendar.MONTH); final int iSelectedDay = calSelected.get(Calendar.DAY_OF_MONTH); boolean isThisMonth = false; //今天在当前月,则去掉默认选中的1号 if (calToday.get(Calendar.YEAR) == iSelectedYear) { if (calToday.get(Calendar.MONTH) == iSelectedMonth) { isThisMonth = true; } } calCalendar.setTimeInMillis(calStartDate.getTimeInMillis()); for (int i = 0; i < mCalendarCells.size(); i++) { CalendarCell dayCell = mCalendarCells.get(i); // final int iYear = calCalendar.get(Calendar.YEAR); final int iMonth = calCalendar.get(Calendar.MONTH); final int iDay = calCalendar.get(Calendar.DAY_OF_MONTH); final int iDayOfWeek = calCalendar.get(Calendar.DAY_OF_WEEK); boolean isOrage=false; boolean isLatDay=false; // 判断是否当天 boolean bToday = false; // 是否被选中 boolean bSelected = false; // check holiday boolean bHoliday = false; // 是否有记录 boolean hasRecord = false; if (calToday.get(Calendar.YEAR) == iYear) { if (calToday.get(Calendar.MONTH) == iMonth) { ThisMonth=iMonth; if (calToday.get(Calendar.DAY_OF_MONTH) == iDay) { Teday=iDay; bToday = true; }else if (calToday.get(Calendar.DAY_OF_MONTH)>iDay) { //判断是不是过去的日期 isLatDay = true; } } } //判断应该变成橘色的数据 if(null!=numberlist){ if (calToday.get(Calendar.YEAR) == iYear) { if (calToday.get(Calendar.MONTH) == iMonth) { for(int j=0;j<numberlist.size();j++){ if(Integer.parseInt(numberlist.get(j))==iDay){ isOrage=true; } } } } } if ((iDayOfWeek == Calendar.SATURDAY) || (iDayOfWeek == Calendar.SUNDAY)){ bHoliday = true; } if ((iMonth == Calendar.JANUARY) && (iDay == 1)){ bHoliday = true; } if (bIsSelection){ if ((iSelectedDay == iDay) && (iSelectedMonth == iMonth) && (iSelectedYear == iYear)) { bSelected = true; }else{ bSelected = false; } } if(iDay==1 && isThisMonth){ bSelected = false; } dayCell.setThisCellDate(iYear, iMonth, iDay, bToday,bSelected, bHoliday,currentMonth, isLatDay,isOrage,hasRecord); calCalendar.add(Calendar.DAY_OF_MONTH, 1); } invalidate(); } /** * 描述:更新日历. */ private void initCalendar() { final boolean bIsSelection = (calSelected.getTimeInMillis() != 0); final int iSelectedYear = calSelected.get(Calendar.YEAR); final int iSelectedMonth = calSelected.get(Calendar.MONTH); final int iSelectedDay = calSelected.get(Calendar.DAY_OF_MONTH); calCalendar.setTimeInMillis(calStartDate.getTimeInMillis()); for (int i = 0; i < mCalendarCells.size(); i++) { CalendarCell dayCell = mCalendarCells.get(i); // final int iYear = calCalendar.get(Calendar.YEAR); final int iMonth = calCalendar.get(Calendar.MONTH); final int iDay = calCalendar.get(Calendar.DAY_OF_MONTH); final int iDayOfWeek = calCalendar.get(Calendar.DAY_OF_WEEK); boolean isOrage=false; boolean isLatDay=false; // 判断是否当天 boolean bToday = false; // 是否被选中 boolean bSelected = false; // check holiday boolean bHoliday = false; if (calToday.get(Calendar.YEAR) == iYear) { if (calToday.get(Calendar.MONTH) == iMonth) { ThisMonth=iMonth; if (calToday.get(Calendar.DAY_OF_MONTH) == iDay) { Teday=iDay; bToday = true; }else if (calToday.get(Calendar.DAY_OF_MONTH)>iDay) { isLatDay=true; } } } //判断应该变成橘色的数据 if(null!=numberlist){ if (calToday.get(Calendar.YEAR) == iYear) { if (calToday.get(Calendar.MONTH) == iMonth) { for(int j=0;j<numberlist.size();j++){ if(Integer.parseInt(numberlist.get(j))==iDay){ isOrage=true; } } } } } if ((iDayOfWeek == Calendar.SATURDAY) || (iDayOfWeek == Calendar.SUNDAY)){ bHoliday = true; } if ((iMonth == Calendar.JANUARY) && (iDay == 1)){ bHoliday = true; } if (bIsSelection){ if ((iSelectedDay == iDay) && (iSelectedMonth == iMonth) && (iSelectedYear == iYear)) { bSelected = true; }else{ bSelected = false; } } dayCell.setThisCellDate(iYear, iMonth, iDay, bToday,bSelected, bHoliday,currentMonth,isLatDay,isOrage,false); calCalendar.add(Calendar.DAY_OF_MONTH, 1); } invalidate(); } /** * Sets the on item click listener. * * @param mAbOnItemClickListener the new on item click listener */ public void setOnItemClickListener(AbOnItemClickListener mAbOnItemClickListener) { this.mOnItemClickListener = mAbOnItemClickListener; } /** * Sets the header height. * * @param height the new header height */ public void setHeaderHeight(int height) { headerHeight = height; mLinearLayoutHeader.removeAllViews(); mCalendarHeader.setLayoutParams(new LayoutParams(width,headerHeight)); mLinearLayoutHeader.addView(mCalendarHeader,new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); this.invalidate(); } /** * Sets the header text size. * * @param size the new header text size */ public void setHeaderTextSize(int size) { mCalendarHeader.setTextSize(size); this.invalidate(); } /** * Rebuild calendar. * * @param calendar the calendar */ public void rebuildCalendar(Calendar calendar) { //初始化选中1号 calSelected.setTimeInMillis(calendar.getTimeInMillis()); initRow(); initStartDateForMonth(); updateCalendar(); } /** 点击日历,触发事件. */ private AbOnItemClickListener mOnDayCellClick = new AbOnItemClickListener(){ @Override public void onClick(int position) { CalendarCell mCalendarCell = mCalendarCells.get(position); //如果为当月的大于等于当天的,则可以点击否则不可以 if( (mCalendarCell.isActiveMonth() && mCalendarCell.getiDateMonth()==ThisMonth && mCalendarCell.getiDateDay()>Teday) || (mCalendarCell.isActiveMonth() && mCalendarCell.getiDateMonth()!=ThisMonth)){ calSelected.setTimeInMillis(mCalendarCell.getThisCellDate().getTimeInMillis()); for(int i=0;i<mCalendarCells.size();i++){ CalendarCell mCalendarCellOther = mCalendarCells.get(i); mCalendarCellOther.setSelected(false); } mCalendarCell.setSelected(true); if(mOnItemClickListener!=null){ mOnItemClickListener.onClick(position); } } } }; /** * 描述:设置标题背景. * * @param resid the new header background resource */ public void setHeaderBackgroundResource(int resid){ mCalendarHeader.setHeaderBackgroundResource(resid); } public void setHeaderBackgroundColor(int resid){ mCalendarHeader.setHeaderBackgroundColor(resid); } /** * 描述:根据索引获取选择的日期. * * @param position the position * @return the str date at position */ public static String getStrDateAtPosition(int position){ CalendarCell mCalendarCell = mCalendarCells.get(position); Calendar calendar = mCalendarCell.getThisCellDate(); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH)+1; int day = calendar.get(Calendar.DATE); final int iWeek=calSelected.get(Calendar.DAY_OF_WEEK)-1; String week; switch (iWeek) { case 1: week="星期一"; break; case 2: week="星期二"; break; case 3: week="星期三"; break; case 4: week="星期四"; break; case 5: week="星期五"; break; case 6: week="星期六"; break; default: week="星期日"; break; } return year+"-"+month+"-"+day+"-"+week; } /** * 描述:获取这个日历的总日期数. * * @return the calendar cell size */ public int getCalendarCellSize(){ return mCalendarCells.size(); } /** * 描述:获取当前日历的所有条目. * * @return the calendar cells */ public ArrayList<CalendarCell> getCalendarCells() { return mCalendarCells; } /** * 描述:获取选中的日期,默认为今天. * * @return the cal selected */ public String getCalSelected() { final int iYear = calSelected.get(Calendar.YEAR); final int iMonth = calSelected.get(Calendar.MONTH)+1; final int iDay = calSelected.get(Calendar.DAY_OF_MONTH); final int iWeek=calSelected.get(Calendar.DAY_OF_WEEK)-1; String week; switch (iWeek) { case 1: week="星期一"; break; case 2: week="星期二"; break; case 3: week="星期三"; break; case 4: week="星期四"; break; case 5: week="星期五"; break; case 6: week="星期六"; break; default: week="星期日"; break; } return iYear+"-"+iMonth+"-"+iDay+"-"+week; } }来自:http://blog.csdn.net/wangchunshun/article/details/32311497