日历选择器
由于公司需求,参看了各个平台的酒店日历选择功能,手动写了一个,就当记录下,代码逻辑可能还需要再去优化下,各位小伙伴没思路的可以参考下。。接下来正题。
看下实现后效果图吧。。
布局上是RecyclerView嵌套RecyclerView,上面2018年月9月是通过自定义RecyclerView.ItemDecoration绘制,代码下面地址有,这里就不解说自定义RecyclerView.ItemDecoration了。。。
((DefaultItemAnimator) mBinding.rv.getItemAnimator()).setSupportsChangeAnimations(false); //当前日期转date SimpleDateFormat ymd_sdf=new SimpleDateFormat("yyyy-MM-dd"); try { if(currentDate==null){ new Throwable("please set one start time"); return; } mSetDate = ymd_sdf.parse(currentDate); } catch (ParseException e) { e.printStackTrace(); } //修改日历对象的日期 Calendar c = Calendar.getInstance(); c.setTime(mSetDate); //获取月份 月份是从0开始需要+1 int firstM= c.get(Calendar.MONTH)+1; //日期 int days=c.get(Calendar.DATE); //周几 int week=c.get(Calendar.DAY_OF_WEEK); //获取当前这个月最大天数 int maxDys=c.getActualMaximum(Calendar.DAY_OF_MONTH); int startDate=0; //日 一 二 三 四 五 六 //- - 当前 //需要求上周末的日期(周末到周一的日期)填补 if("1".equals(week+"")){ //今天是否周末 startDate=days; }else { //获取上周末 startDate= Integer.parseInt(CalendarUtil.getPreviousWeekSundayByDate(ymd_sdf.format(mSetDate)).split("-")[2]); } DateInfo info = new DateInfo(); List<DayInfo> dayList=new ArrayList<>(); info.setDate(c.get(Calendar.YEAR)+ "年" + firstM + "月"); //根据周末日期开始计算到结尾日期的天数 //当小于当前日期时,是不可选,setEnable(false) //如果上周末是大于当前的,说明上周末是上个月的 //如何判断呢,1,当前日期小于周末则是上个月 2,其他情况是当前日期肯定会大于周末 if(days<startDate){ //计算上个月在本周日历的日期 //获取上月最后一天的日期 String previousMonthLastDate=CalendarUtil.getPreviousMonthEndByDate(ymd_sdf.format(mSetDate)); int previousMonthLastDay= Integer.parseInt(previousMonthLastDate.split("-")[2]); LogUtil.debugE("previousMonthLastDay",previousMonthLastDay+""); //从上个月周日日期算起,到上个月最后一天的日期 for (int i=startDate;i<=previousMonthLastDay;i++){ DayInfo dayInfo=new DayInfo() ; dayInfo.setName(i+""); dayInfo.setEnable(false); dayInfo.setDate(previousMonthLastDate.split("-")[0]+"-"+previousMonthLastDate.split("-")[1]); dayList.add(dayInfo); } //计算完后,回归为1号,计算当前这个月日期 startDate=1; } //计算当前月的天数 for (int i=startDate ; i<=maxDys;i++){ DayInfo dayInfo=new DayInfo() ; dayInfo.setName(i+""); dayInfo.setDate(c.get(Calendar.YEAR)+"-"+(c.get(Calendar.MONTH)+1)+"-"+i); int c_year= Integer.parseInt(currentDate.split("-")[0]); int c_month= Integer.parseInt(currentDate.split("-")[1]); int c_day= Integer.parseInt(currentDate.split("-")[2]); if(c_year==c.get(Calendar.YEAR) && c_month==(c.get(Calendar.MONTH)+1) && c_day==i){ dayInfo.setName("今天"); c_stratChildPosition=dayList.size(); } if(c_year==c.get(Calendar.YEAR) && c_month==(c.get(Calendar.MONTH)+1) && c_day+1==i){ dayInfo.setName("明天"); } if(i<days){ dayInfo.setEnable(false); }else { dayInfo.setEnable(true); } dayList.add(dayInfo); } info.setList(dayList); mList.add(info);
以上是计算当前月的日历表,currentDate是从服务器拉取的时间,这里我们可以模仿下,设定一个日期yyyy-MM-dd,获取Calendar对象,设置时间为currentDate。以周日-周六为标准。首先理清下 ,计算第一个周末是上个月的周日还是本月的周日,如果是上个月周末,我们需要获取上个周日的日期和上个月最后一个月的最后一天日期,计算相差的日期。如果第一个周日是本月,则当前日期肯定大于上周日的日期。
//获取下3个月的数据 for (int i=1 ;i<8;i++){ //当前月份循环加1 c.add(Calendar.MONTH,01); DateInfo nextInfo = new DateInfo(); List<DayInfo> nextdayList=new ArrayList<>(); int maxDays=c.getActualMaximum(Calendar.DAY_OF_MONTH); nextInfo.setDate(c.get(Calendar.YEAR)+ "年" + (c.get(Calendar.MONTH)+1) + "月"); //周几 int weeks=CalendarUtil.getWeekNoFormat(c.get(Calendar.YEAR)+"-"+(c.get(Calendar.MONTH)+1)+"-01")-1; LogUtil.debugE("---",weeks+""); //根据该月的第一天,星期几,填充上个月的空白日期 for (int t=0;t<weeks;t++){ DayInfo dayInfo=new DayInfo() ; dayInfo.setName(""); dayInfo.setEnable(false); dayInfo.setDate(""); nextdayList.add(dayInfo); } //该月的所有日期 for (int j=0;j<maxDays;j++){ DayInfo dayInfo=new DayInfo() ; dayInfo.setName((j+1)+""); dayInfo.setEnable(true); dayInfo.setDate(c.get(Calendar.YEAR)+"-"+(c.get(Calendar.MONTH)+1)+"-"+(j+1)); nextdayList.add(dayInfo); } nextInfo.setList(nextdayList); mList.add(nextInfo); LogUtil.debugE("--",c.getActualMaximum(Calendar.DAY_OF_MONTH)+"-"+c.get(Calendar.YEAR)+"-"+c.get(Calendar.MONTH)); }
计算后3个月的日历日期,这部分好算,根据Calendar计算每个月的最大天数。获取每个月的第一天的日期,判断是否是周末,是周末,我们直接new Dayinfo添加,否则的话,我们需要根据第一天计算出周几,往后退到周日的日期,添加空数据。
//设置日历标明今天明天 public void setDefaultSelect(){ if(c_stratChildPosition==-1)return; String date=mList.get(0).getList().get(c_stratChildPosition).getDate(); LogUtil.debugE("zuixina---",date); SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); Date curDate=null; try { curDate=sdf.parse(FormatDate(date)); } catch (ParseException e) { e.printStackTrace(); } if(curDate==null)return; Calendar calendar= Calendar.getInstance(); calendar.setTime(curDate); calendar.add(Calendar.DATE,1); int year= Integer.parseInt(date.split("-")[0]); int month= Integer.parseInt(date.split("-")[1]); if(year==calendar.get(Calendar.YEAR) && month==calendar.get(Calendar.MONTH)+1 && c_stratChildPosition<mList.get(0).getList().size()-1){ setInit(0,c_stratChildPosition,0,c_stratChildPosition+1); }else { for (int i=0;i<mList.get(1).getList().size();i++){ if(!TextUtils.isEmpty(mList.get(1).getList().get(i).getDate())){ setInit(0,c_stratChildPosition,1,i); break; } } } LogUtil.debugE("zusixin---",calendar.get(Calendar.YEAR)+"-"+calendar.get(Calendar.MONTH)+"-"+calendar.get(Calendar.DATE)); // }
该方法根据c_stratChildPosition,这个是currentDate日期在数组列表的位置标识,根据该标识去初始化默认的“今天”“明天”。
大概的计算也就这几个地方,其他的基本都是刷新逻辑,代码里注释也比较详细。可以参考代码来理解。。。。写的不好请多多谅解。。。谢谢各位。