CalendarListView 源码解析
本文为 CalendarListView 中 CalanderListView 部分
项目地址:CalendarListView,分析的版本:063952b,Demo 地址:calendar-list-view-demo
分析者:Rogary,分析状态:未完成,校对者:Trinea,校对状态:未开始
1. 功能介绍
calendarlistview 选取提供了一个 API 10+日历日期的简便方法
只需要在你的布局中添加 datepickerview 无需定制。
使用控件 RecycleView 实现的日期选择器,可以选择时间段。
1.1 完成时间
2015-2-12完成
1.2 集成指南
lib 已经上传至 Maven 库
在 gradle 中
dependencies {
compile 'com.github.traex.calendarlistview:library:1.2.2'
}
1.3 使用指南
1.在你的布局 XML 声明一个
DayPickerView``` xml
```
2.在你的 Activity 或 Fragment 中引入
DatePickerController,然后你需要设置getMaxYearand >onDayOfMonthSelected.
getMaxYear是设置选择器的最大年数
onDayOfMonthSelected是当你选择了某个新日期时的回调``` java
@Override
public int getMaxYear()
{
return 2015;
}
@Override
public void onDayOfMonthSelected(int year, int month, int day)
{
Log.e("Day Selected", day + " / " + month + " / " + year);
}
```
1.4 如何定制
app:colorCurrentDay [color def:#ff999999] --> 当前日期固定为粗体,但你可以定制颜色
app:colorSelectedDayBackground [color def:#E75F49] --> 点击的日期的背景圆形或圆角矩形的颜色
app:colorSelectedDayText [color def:#fff2f2f2] --> 已选择天数的文字颜色
app:colorPreviousDay [color def:#ff999999] --> 当前日期之前的颜色
app:colorNormalDay [color def:#ff999999] --> 默认日期的颜色
app:colorMonthName [color def:#ff999999] --> 月名和年名的默认颜色
app:colorDayName [color def:#ff999999] --> 日期名字的默认颜色
app:textSizeDay [dimension def:16sp] --> 日期数字的文本大小
app:textSizeMonth [dimension def:16sp] --> 月份的文本大小
app:textSizeDayName [dimension def:10sp] --> 日期名的文本大小
app:headerMonthHeight [dimension def:50dip] --> 顶部月份栏的高度
app:drawRoundRect [boolean def:false] --> 选中天数使用圆角矩形而不是使用圆形
app:selectedDayRadius [dimension def:16dip] --> 如果使用圆角矩形,设置圆角矩形的半径
app:calendarHeight [dimension def:270dip] --> 月或行的行距
app:enablePreviousDay [boolean def:true] --> 启用已过期的天数
app:currentDaySelected [boolean def:false] --> 默认选中当前日期
app:firstMonth [enum def:-1] --> 默认起始月份
app:lastMonth [enum def:-1] --> 默认结束月份
2. 详细设计
2.1 类详细介绍
1.
DayPickerView
DayPickerView继承于RecyclerViewRecyclerView相关知识
在这里 DayPickerView 作为整个 Calendar—list-view 的容器
目前 SDK 中提供了三种自带的 LayoutManager:
LinearLayoutManager
GridLayoutManager
StaggeredGridLayoutManager
这里用到了 LinearLayoutManager
LinearLayoutManager 可设置方向,这里使用默认的竖向
(1) 主要成员变量含义
>
1.mCurrentScrollState 当前滑动状态
2.mPreviousScrollPosition 之前滑动的位置
3.mPreviousScrollState 之前的滑动状态
2.
SimpleMonthAdapter
SimpleMonthAdapter继承于RecyclerView.AdapterRecyclerView 跟 ListView 一样,需要设置 RecyclerView 的 Adapter,但是这里的 Adapter 跟 ListView 使用的 Adapter 不一样,这里的 Adapter 需要继承 RecyclerView.Adapter,需要实现 3 个方法:
- onCreateViewHolder()
- onBindViewHolder()
- getItemCount()
onCreateViewHolder(ViewGroup viewGroup, int i)
这个方法主要生成为每个 Item inflater 出一个 View,但是该方法返回的是一个 ViewHolder。方法是把 View 直接封装在 ViewHolder 中,然后我们面向的是 ViewHolder 这个实例,这里的 ViewHolder 即
SimpleMonthView。直接省去了当初的 convertView.setTag(holder)和 convertView.getTag()这些繁琐的步骤。onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i)
这个方法主要用于适配渲染数据到 View 中。方法提供给你了一个 viewHolder,而不是原来的 convertView。
这里与 ListViewAdapter 做一个对比
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if(null == convertView){ holder = new ViewHolder(); LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = mInflater.inflate(R.layout.item, null); holder.btn = (Button) convertView.findViewById(R.id.btn); holder.tv = (TextView) convertView.findViewById(R.id.tv); holder.iv = (TextView) convertView.findViewById(R.id.iv); convertView.setTag(holder); }else{ holder = (ViewHolder) convertView.getTag(); } final HashMap<String, Object> map = list.get(position); holder.iv.setImageResource(Integer.valueOf(map.get("iv").toString())); holder.tv.setText(map.get("tv").toString()); holder.btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(context, map.get("btn").toString(), Toast.LENGTH_SHORT).show(); } }); return convertView; } class ViewHolder{ Button btn; ImageView iv; TextView tv; }旧的写法中 Line5~Line12+Line28 部分的代码其实起到的作用相当于新的写法的 onCreateViewHolder();
旧的写法中 Line14~Line26 部分的代码其实起到的作用相当于新的写法的 onBindViewHolder();
(1) 主要成员变量含义
1.
selectedDays选中的日期
2.firstMonth开始的月份
3.lastMonth结束的月份(2) 核心方法
setSelectedDay()当日期被点击 流程图为:
![]()
3.
SimpleMonthView
SimpleMonthView继承于View
SimpleMonthView这里作为 RecycleView 的 Item 项,以月份为单位绘制View 绘制流程函数调用链
图片来自 https://plus.google.com/+ArpitMathur/posts/cT1EuBbxEgN
(1) 主要成员变量含义
1.
mHasToday本月中含有今天
2.mIsPrev是否是过去的月份
3.mSelectedBeginDay选中的开始日期
4.mSelectedLastDay选中的结束日期
5.mSelectedBeginMonth选中的开始日期所在的月份
6.mSelectedLastMonth选中的结束日期所在的月份
7.mSelectedBeginYear选中的开始日期所在的年份
8.mSelectedLastYear选中的结束日期所在的年份
9.mToday今天
10.mNumDays本月所含的天数
11.mWeekStart每周开始是星期几
12.mDayOfWeekStart结束的月份
13.mMonth当前月份
14.mDrawRect选中标记是圆角矩形
15.mRowHeight行高
16.mWidth屏幕宽度
17.mYear当前年份
18.isPrevDayEnabled是否可选今天以前的日期
19.mNumRows日期的行数(2) 核心方法
onDraw()流程图![]()
protected void onDraw(Canvas canvas) { drawMonthTitle(canvas); //绘制月份头部 drawMonthDayLabels(canvas); //绘制日期表格 drawMonthNums(canvas); //绘制日期 }4.
DatePickerController
DatePickerController日期选择 Controller 接口,在使用时需要实现以下接口public abstract int getMaxYear(); public abstract void onDayOfMonthSelected(int year, int month, int day); public abstract void onDateRangeSelected(final SimpleMonthAdapter.SelectedDays<SimpleMonthAdapter.CalendarDay> selectedDays);getMaxYear() :设置最大年份
onDayOfMonthSelected(int year, int month, int day) :点击日期时的操作
onDateRangeSelected(final SimpleMonthAdapter.SelectedDays
selectedDays) :选择了两个日期时的处理 5.
CalendarUtils
CalendarUtilspublic static int getDaysInMonth(int month, int year) :获取月份相应的天数
3. 总体设计
图片来自
