需求描述:
市场上很多App都会有签到功能,实现方式不尽相同,有直接展示整张日历的,也有只提供近7日或15日的签到情况的。我遇到的需求是展示一张包含35天的日历,没有翻页功能,但当前日期必须在日历最中间的那一行,我去,人家的日历都是整月整月的展示,你家日历咋这么特殊呢?PM给出的理由是“必须让用户看到连续签到的情况啊”。行,你说啥就是啥,大不了我自己一天一天的算呗!实话实说,PM提出的需求,只要合法合理,咱就去做,在做的过程中也可以提升自我,何乐而不为呢。但是如果遇到让根据手机壳改变App主题这样变态的需求,我们还是要斟酌一下的,哈哈!废话不多说,解决问题吧!
总结一下需求:
1、展示共35天的日期,五行七列;
2、当天日期必须处在日历最中间的一行,也就是第三行。
效果图:
解决思路:
1、用两个网格布局的RecyclerView分别展示日历的星期和日期;
2、获取当天日期在日历中所处的位置,由于当天日期是展示在第三行的,每行有七个日期,位置从零开始算,也就是第三行是从第14个位置到第20个位置;
3、大家会问,知道这些我们还是无法确定当天日期到底在第三行的哪个位置啊?不要着急,我通过获取当天日期所对应周几,得到周日对应0,周一对应1,以此类推周六对应6,发现和14相加,正好是我们想要的位置!ok!bingo!
4、知道了当天所处的位置,我们就可以分别向前和向后推算总共35个日期,一张日历就搞定了!
核心代码:
Activity中的代码:
private DateAdapter dateAdapter;
private List<SignDateModel> models = new ArrayList<>(35);
private int current;
private void initData() {
current = 14 + DateUtil.getCurrentDayOfWeek() - 1; //今天在日历中的位置
for (int i = 0; i < current + 1; i++) {
SignDateModel model = new SignDateModel();
//初始化前半部分日历数据
model.setContent(String.valueOf(DateUtil.getDateForLastDay(current - i).getDate()));
if (DateUtil.getDateForLastDay(current - i).getDay() == 0 ||
DateUtil.getDateForLastDay(current - i).getDay() == 6) {
model.setStatus(SignDateModel.STATUS_SAT_OR_SUN);
}
if (current - i == 0) {
model.setStatus(SignDateModel.STATUS_CURRENT_DAY);
}
models.add(i, model);
}
int after = 34 - current; //今天之后需要补齐多少天
for (int i = 1; i < after + 1; i++) {
SignDateModel model = new SignDateModel();
//初始化后半部分日历数据
model.setContent(String.valueOf(DateUtil.getDateForNextDay(i).getDate()));
if (DateUtil.getDateForNextDay(i).getDay() == 0 ||
DateUtil.getDateForNextDay(i).getDay() == 6) {
model.setStatus(SignDateModel.STATUS_SAT_OR_SUN);
}
models.add(current + i, model);
}
dateAdapter.setData(models);
}
实体类SignDateModel代码:
/**
* Created by kangbaibai on 2018/8/27.
* 签到日期
*/
public class SignDateModel {
public static final int STATUS_NO_SIGN = 0; //0 未签到的日期
public static final int STATUS_HAVE_SIGN = 1; //1 已签到的日期
public static final int STATUS_SAT_OR_SUN = 2; //2 周六或周日
public static final int STATUS_CURRENT_DAY = 3; //3 今天日期
public SignDateModel() {
this.status = STATUS_NO_SIGN;
}
public SignDateModel(int status, String content) {
this.status = status;
this.content = content;
}
private int status; //签到状态
private String content; //要展示的文字
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
日期获取和转换相关的工具类DateUtil代码:
public class DateUtil {
//获取今天是星期几
public static int getCurrentDayOfWeek() {
Calendar calendar = Calendar.getInstance();//日历对象
calendar.setTime(new Date());//设置当前日期
int i = calendar.get(Calendar.DAY_OF_WEEK);
return i;
}
//获取前一天的日期
public static Date getDateForLastDay(int amount) {
Calendar ca = Calendar.getInstance();//得到一个Calendar的实例
ca.setTime(new Date()); //设置时间为当前时间
ca.add(Calendar.DATE, -amount);
Date lastDay = ca.getTime(); //结果
//前一年ca.add(Calendar.YEAR, -1);
//求前一月ca.add(Calendar.MONTH, -1),
//前一天ca.add(Calendar.DATE, -1)
//lastDay.getDay()周几 lastDay.getDate()日期
return lastDay;
}
//获取后一天的日期
public static Date getDateForNextDay(int amount) {
Calendar ca = Calendar.getInstance();//得到一个Calendar的实例
ca.setTime(new Date()); //设置时间为当前时间
ca.add(Calendar.DATE, +amount);
Date lastDay = ca.getTime(); //结果
return lastDay;
}
}
计算过程主要用到了Calendar类和它的一些api,很简单,希望能帮到大家,或者给大家提供一个思路!觉得有用的顶一下~谢谢!