GLCalendarView - a Fully Customizable Date Range Picker

GLCalendarView是Glow的第二个开源项目,虽然开源的calendar有很多,但是支持range的却很少,我们对GLCalendarView的定位是date range picker,希望它可以帮助到其他开发者~

Demo

GLCalendarView

Installation

CocoaPods

如果你使用cocoapods,那么只需将GLCalendarView加入PodFile

pod "GLCalendarView", "~> 1.0.0"

Source File

或者可以将 Sources 目录下的所有文件拷贝进项目

Usage

  • 在storyboard里放置一个view,或者用代码创建,将view的class设置成GLCalendarView
  • viewDidLoad里, 对calendar view进行一些设置,例如设置 firstDatelastDate
  • viewWillAppear里, 设置需要显示的ranges,调用 [calendarView reload]; 来刷新数据

如果要在calendar view里显示一些range,需要构造一些GLCalendarDateRange objects,把它们设置成calendar view的model:

NSDate *today = [NSDate date];
NSDate *beginDate = [GLDateUtils dateByAddingDays:-23 toDate:today];
NSDate *endDate = [GLDateUtils dateByAddingDays:-18 toDate:today];
GLCalendarDateRange *range = [GLCalendarDateRange rangeWithBeginDate:beginDate endDate:endDate];
range.backgroundColor = COLOR_BLUE;
range.editable = YES;
range.binding = yourModelObject // you can bind your model to the range

self.calendarView.ranges = [@[range1] mutableCopy];
[self.calendarView reload];

这里说明一下binding field,它的作用是允许把自己的model绑定到range上,这样当range被update的时候,可以很方便地从range上拿到对应的model,然后更新这个model。

calendar view会处理所有的用户交互,包括新增,修改,和删除一个range,所有的这些事件都可以通过delegate protocol来监听:

@protocol GLCalendarViewDelegate <NSObject>
- (BOOL)calenderView:(GLCalendarView *)calendarView canAddRangeWithBeginDate:(NSDate *)beginDate;
- (GLCalendarDateRange *)calenderView:(GLCalendarView *)calendarView rangeToAddWithBeginDate:(NSDate *)beginDate;
- (void)calenderView:(GLCalendarView *)calendarView beginToEditRange:(GLCalendarDateRange *)range;
- (void)calenderView:(GLCalendarView *)calendarView finishEditRange:(GLCalendarDateRange *)range continueEditing:(BOOL)continueEditing;
- (BOOL)calenderView:(GLCalendarView *)calendarView canUpdateRange:(GLCalendarDateRange *)range toBeginDate:(NSDate *)beginDate endDate:(NSDate *)endDate;
- (void)calenderView:(GLCalendarView *)calendarView didUpdateRange:(GLCalendarDateRange *)range toBeginDate:(NSDate *)beginDate endDate:(NSDate *)endDate;
@end

可以这样实现:

- (BOOL)calenderView:(GLCalendarView *)calendarView canAddRangeWithBeginDate:(NSDate *)beginDate
{
    // you should check whether user can add a range with the given begin date
    return YES;
}

- (GLCalendarDateRange *)calenderView:(GLCalendarView *)calendarView rangeToAddWithBeginDate:(NSDate *)beginDate
{
    // construct a new range object and return it
    NSDate* endDate = [GLDateUtils dateByAddingDays:2 toDate:beginDate];
    GLCalendarDateRange *range = [GLCalendarDateRange rangeWithBeginDate:beginDate endDate:endDate];
    range.backgroundColor = [UIColor redColor];
    range.editable = YES;
    range.binding = yourModel // bind your model to the range instance
    return range;
}

- (void)calenderView:(GLCalendarView *)calendarView beginToEditRange:(GLCalendarDateRange *)range
{
    // save the range to a instance variable so that you can make some operation on it
    self.rangeUnderEdit = range;
}

- (void)calenderView:(GLCalendarView *)calendarView finishEditRange:(GLCalendarDateRange *)range continueEditing:(BOOL)continueEditing
{
    // retrieve the model from the range, do some updates to your model
    id yourModel = range.binding;
    self.rangeUnderEdit = nil;
}

- (BOOL)calenderView:(GLCalendarView *)calendarView canUpdateRange:(GLCalendarDateRange *)range toBeginDate:(NSDate *)beginDate endDate:(NSDate *)endDate
{
    // you should check whether the beginDate or the endDate is valid
    return YES;
}

- (void)calenderView:(GLCalendarView *)calendarView didUpdateRange:(GLCalendarDateRange *)range toBeginDate:(NSDate *)beginDate endDate:(NSDate *)endDate
{
    // update your model if necessary
    id yourModel = range.binding;
}

Appearance

GLCalendarView 的 appearance是高度可定制的,可以通过appearance api来设置所有的字体,颜色,边框等:

[GLCalendarView appearance].rowHeight = 54;
[GLCalendarView appearance].padding = 6;
[GLCalendarView appearance].weekDayTitleAttributes = @{NSFontAttributeName:[UIFont systemFontOfSize:8], NSForegroundColorAttributeName:[UIColor grayColor]};
[GLCalendarView appearance].monthCoverAttributes = @{NSFontAttributeName:[UIFont systemFontOfSize:30]};

[GLCalendarDayCell appearance].dayLabelAttributes = @{NSFontAttributeName:[UIFont systemFontOfSize:20], NSForegroundColorAttributeName:UIColorFromRGB(0x555555)};
[GLCalendarDayCell appearance].monthLabelAttributes = @{NSFontAttributeName:[UIFont systemFontOfSize:8]};
    
[GLCalendarDayCell appearance].editCoverBorderWidth = 2;
[GLCalendarDayCell appearance].editCoverBorderColor = UIColorFromRGB(0x366aac);
[GLCalendarDayCell appearance].editCoverPointSize = 14;

[GLCalendarDayCell appearance].todayBackgroundColor = UIColorFromRGB(0x366aac);
[GLCalendarDayCell appearance].todayLabelAttributes = @{NSFontAttributeName:[UIFont systemFontOfSize:20]};

[GLCalendarDayCell appearance].rangeDisplayMode = RANGE_DISPLAY_MODE_CONTINUOUS;

最后附上project: https://github.com/Glow-Inc/GLCalendarView