CalendarPickerView
源码解析
项目相关
TimesSquare
是一个开源的日历控件。
其项目托管地址是:
https://github.com/square/android-times-square
先看一下程序
Sample
运行截图:
此
libs
的程序结构如下:
很简单,基本上从命名上就可以区分每个类的作用。下面我用一张图来帮大家梳理一下这些类的作用:
上面的图片中我们可以看出
CalendarPickerView
是
ListView
的子类,那么就一定会有一个
Adapter
用来为它适配数据,我们就先从这个适配器说起——
MonthAdapter
。
- private class MonthAdapter extends BaseAdapter {
- private final LayoutInflater inflater;
- ... ...
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- MonthView monthView = (MonthView) convertView;
- if (monthView == null) {
- monthView = MonthView.create(parent, inflater, weekdayNameFormat,
- listener, today);
- }
- monthView.init(months.get(position), cells.get(position));
- return monthView;
- }
- }
复制代码
正如上图所示
getView
返回的视图就是
MonthView
。下面我们看一下
MonthView
的
create()
方法
:
- public static MonthView create(ViewGroup parent, LayoutInflater inflater,
- DateFormat weekdayNameFormat, Listener listener, Calendar today) {
- final MonthView view = (MonthView) inflater.inflate(R.layout.month, parent,
- false);
- final int originalDayOfWeek = today.get(Calendar.DAY_OF_WEEK);
- //========
- // 配置grid header,比如:周一、周日这些文字
- //========
- int firstDayOfWeek = today.getFirstDayOfWeek();
- final CalendarRowView headerRow = (CalendarRowView) view.grid.getChildAt(0);
- for (int offset = 0; offset < 7; offset++) {
- today.set(Calendar.DAY_OF_WEEK, firstDayOfWeek + offset);
- final TextView textView = (TextView) headerRow.getChildAt(offset);
- textView.setText(weekdayNameFormat.format(today.getTime()));
- }
- ... ...
- }
复制代码
在
create
方法里面只是配置了
grid header
的文字,并没有把相应的日期对应到布局上去,那么是在什么地方真正负责日期与布局的对应呢?在上面
CalendarPickerView
的适配器的
getView
方法中除了调用
MonthView
的
create
方法创建了
MonthView
对象,还调用了
init
方法,我们来看一看这个方法:
- public void init(MonthDescriptor month, List<List<MonthCellDescriptor>> cells) {
- ... ...
- final int numRows = cells.size();
- grid.setNumRows(numRows);
- for (int i = 0; i < 6; i++) {//at most 5 rows per month
- CalendarRowView weekRow = (CalendarRowView) grid.getChildAt(i + 1);
- weekRow.setListener(listener);
- if (i < numRows) {
- weekRow.setVisibility(VISIBLE);
- List<MonthCellDescriptor> week = cells.get(i);
- for (int c = 0; c < week.size(); c++) {
- MonthCellDescriptor cell = week.get(c);
- CalendarCellView cellView = (CalendarCellView) weekRow.getChildAt(c);
- cellView.setText(Integer.toString(cell.getValue()));
- ... ...
- }
- } else {
- weekRow.setVisibility(GONE);
- }
- }
-
- }
复制代码
果然这里就是日期与布局绑定的地方。这里
cells
是一个
List<List<MonthCellDescriptor>>
类型的数据,其中
MonthCellDescriptor
这个就是一个对每月中的每一天进行描述的实体类,
cells
表示一整个月的日期(为了填满这个表格我们还会显示上个月和下个月的日期),而
cells
列表中的每一项恰好是一个星期的日期。这样我们就可以把日期绑定到
CalendarCellView
这个最小的
TextView
显示日期了。
至此我们就简单的了解一下
TimesSquare
源码结构。本套开源框架实现起来并不复杂,很容易理解,只要细心阅读大家都可以读懂,也可以在此基础上开发满足自己需求的控件。
最后提供一下最近下载的项目文件,建议大家还是项目托管处下载最新源码。