java 按月分组_android日历选择按月分组并用recyclerview展示

今天分享一个日历选择控件,可以定义日期可选、选择范围、按月分组展示。这个日历无非就是把每个日期的数据通过系统的日历查询出来,然后用recyclerview展示即可,数据模型里可以定义哪些可选以及选定状态等等。思路就是这样了,先看看效果:

bd21d8d9422f

日历效果

首先定义好数据来源,即从系统的calendar获取日期列表,这里因为是要按月分组,所以我选择用一个key为月份的时间戳value为对应月份的所有日期list的map来接收查询出来的日历,在展示的时候把map转为分组的list即可:

import android.annotation.SuppressLint;

import androidx.annotation.NonNull;

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.ArrayList;

import java.util.Calendar;

import java.util.Date;

import java.util.LinkedHashMap;

/**

* 日历工具类

* @author ly

* date 2020/4/24 9:52

*/

public class CalendarUtils {

public final static String YEAR = "yyyy";

public final static String YEAR_MONTH = "yyyy年MM月";

public final static String MONTH_DAY = "MM-dd";

public final static String DATE = "yyyy-MM-dd";

public final static String TIME = "HH:mm";

public final static String MONTH_DAY_TIME = "MM月dd日 hh:mm";

public final static String DATE_TIME_SECOND = "yyyy-MM-dd HH:mm:ss";

public final static String DATE_TIME = "yyyy-MM-dd HH:mm";

public final static String DATE1_TIME = "yyyy/MM/dd HH:mm";

public static @NonNull

LinkedHashMap> getMonthMap(Calendar initialCalendar, int monthNum) {

return getMonthMap(initialCalendar, monthNum, Integer.MAX_VALUE);

}

public static @NonNull

LinkedHashMap> getMonthByLimit(Calendar initialCalendar, int validSelNumLimit) {

return getMonthMap(initialCalendar, Integer.MAX_VALUE, validSelNumLimit);

}

/**

* 以月为单位,获取每个月的日期列表

*

* @param initialCalendar 初始选中的日期

* @param validSelNumLimit 最大有效选中数量

* @return 返回一个key为当前loop月的时间戳,value为当前月的所有日期list的有序map

* @author ly on 2020/4/25 11:37

*/

public static @NonNull

LinkedHashMap> getMonthMap(Calendar initialCalendar, int monthNum, int validSelNumLimit) {

//key:当前loop月的时间戳 value:当前月的所有日期list

LinkedHashMap> dateMap = new LinkedHashMap<>();

ArrayList dateInMonthList = new ArrayList<>();

if (initialCalendar == null)

initialCalendar = Calendar.getInstance();

Calendar c = Calendar.getInstance();

//设置开始遍历的date

//也可以不使用下面的set,直接c.setTime(initialCalendar.getTime()),只是第一个月的数据可能不足那个月的最大天数(ui不美观)

//告诉calendar从指定月的第一天开始,而不是精确到某一天

c.set(initialCalendar.get(Calendar.YEAR), initialCalendar.get(Calendar.MONTH), 1);

int loopMonthCount = 0;

int validDateNum = 0;//有效的可选日期数量

while (loopMonthCount < monthNum) {

// 获取当前月最大天数

int maxDayNum = c.getActualMaximum(Calendar.DATE);

int month = c.get(Calendar.MONTH);

DateInfo dateInfo = new DateInfo();

dateInfo.year = c.get(Calendar.YEAR);

dateInfo.month = month + 1;

dateInfo.day = c.get(Calendar.DAY_OF_MONTH);

dateInfo.timestamp = c.getTimeInMillis();

dateInfo.week = c.get(Calendar.DAY_OF_WEEK);

dateInfo.isSelected = initialCalendar.get(Calendar.MONTH) == c.get(Calendar.MONTH) && initialCalendar.get(Calendar.DATE) == c.get(Calendar.DATE);

//是否为可选的日期

boolean isAvailableDate = (dateInfo.isSelected || c.after(initialCalendar)) && dateInfo.week != Calendar.SUNDAY && dateInfo.week != Calendar.SATURDAY;

if (isAvailableDate)

validDateNum++;

dateInfo.canSelect = isAvailableDate && validDateNum <= validSelNumLimit;

if (dateInMonthList.isEmpty()) {//在每一月的第一周前面补空data

for (int j = 0; j < dateInfo.week - 1; j++) {

DateInfo d = new DateInfo();

dateInMonthList.add(0, d);

}

}

dateInMonthList.add(dateInfo);

if (maxDayNum == dateInfo.day) {//每loop到月底put一次

dateMap.put(dateInfo.timestamp, new ArrayList<>(dateInMonthList));

dateInMonthList.clear();

if (validDateNum < validSelNumLimit) {

loopMonthCount++;

} else {

break;//达到最大可选数后自动跳出looper

}

}

//条件满足时一直add天数即可

c.add(Calendar.DATE, 1);

}

return dateMap;

}

public static @NonNull

LinkedHashMap> getMonthMap(String startDate, String endDate) {

//key:当前loop月的时间戳 value:当前月的所有日期list

LinkedHashMap> dateMap = new LinkedHashMap<

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值