项目中需要用到日历控件,在code4app上找到一款简洁简单的《VurigCalendar》,改写前后界面如下:
主要改写了drawRect中周日背景、日期背景、今天和选中日背景、日期标记。代码如下:
- (void)drawRect:(CGRect)rect
{
int firstWeekDay = [self.currentMonth firstWeekDayInMonth]-1; //-1 because weekdays begin at 1, not 0
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy年M月"];
labelCurrentMonth.text = [formatter stringFromDate:self.currentMonth];
[labelCurrentMonth sizeToFit];
labelCurrentMonth.frameX = roundf(self.frame.size.width/2 - labelCurrentMonth.frameWidth/2);
labelCurrentMonth.frameY = 10;
[formatter release];
[currentMonth firstWeekDayInMonth];
CGContextClearRect(UIGraphicsGetCurrentContext(),rect);
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect rectangle = CGRectMake(0, 0, self.frame.size.width, self.size.height);
CGContextAddRect(context, rectangle);
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextFillPath(context);
rectangle = CGRectMake(0,kVRGCalendarViewTopBarHeight-16,self.frame.size.width,16);
CGContextAddRect(context, rectangle);
CGContextSetFillColorWithColor(context, COLOR(193, 193, 193).CGColor);
CGContextFillPath(context);
//Arrows
int arrowSize = 12;
int xmargin = 80;
int ymargin = 15;
//Arrow Left
CGContextBeginPath(context);
CGContextMoveToPoint(context, xmargin+arrowSize/1.5, ymargin);
CGContextAddLineToPoint(context,xmargin,ymargin+arrowSize/2);
CGContextAddLineToPoint(context,xmargin+arrowSize/1.5,ymargin+arrowSize);
CGContextSetStrokeColorWithColor(context, COLOR(57, 151, 243).CGColor);
CGContextSetLineWidth(context, 2);
CGContextDrawPath(context, kCGPathStroke);
//Arrow right
CGContextBeginPath(context);
CGContextMoveToPoint(context, self.frame.size.width-(xmargin+arrowSize/1.5), ymargin);
CGContextAddLineToPoint(context,self.frame.size.width-xmargin,ymargin+arrowSize/2);
CGContextAddLineToPoint(context,self.frame.size.width-(xmargin+arrowSize/1.5),ymargin+arrowSize);
CGContextSetStrokeColorWithColor(context, COLOR(57, 151, 243).CGColor);
CGContextSetLineWidth(context, 2);
CGContextDrawPath(context, kCGPathStroke);
//Weekdays
NSArray *weekdays = @[@"一", @"二", @"三", @"四", @"五", @"六", @"日"];
CGContextSetFillColorWithColor(context, [UIColor colorWithHexString:@"0xffffff"].CGColor);
for (int i =0; i<[weekdays count]; i++) {
NSString *weekdayValue = (NSString *)[weekdays objectAtIndex:i];
UIFont *font = [UIFont systemFontOfSize:10.0f];
[weekdayValue drawInRect:CGRectMake(i*(kVRGCalendarViewDayWidth)+2, 46, kVRGCalendarViewDayWidth, 16) withFont:font lineBreakMode:NSLineBreakByClipping alignment:NSTextAlignmentCenter];
}
int numRows = [self numRows];
//Draw days
CGContextSetFillColorWithColor(context, [UIColor colorWithHexString:@"0x333333"].CGColor);
int numBlocks = numRows*7;
NSDate *previousMonth = [self.currentMonth offsetMonth:-1];
int currentMonthNumDays = [currentMonth numDaysInMonth];
int prevMonthNumDays = [previousMonth numDaysInMonth];
int selectedDateBlock = ([selectedDate day]-1)+firstWeekDay;
//prepAnimationPreviousMonth nog wat mee doen
//prev next month
BOOL isSelectedDatePreviousMonth = prepAnimationPreviousMonth;
BOOL isSelectedDateNextMonth = prepAnimationNextMonth;
if (self.selectedDate!=nil) {
isSelectedDatePreviousMonth = ([selectedDate year]==[currentMonth year] && [selectedDate month]<[currentMonth month]) || [selectedDate year] < [currentMonth year];
if (!isSelectedDatePreviousMonth) {
isSelectedDateNextMonth = ([selectedDate year]==[currentMonth year] && [selectedDate month]>[currentMonth month]) || [selectedDate year] > [currentMonth year];
}
}
if (isSelectedDatePreviousMonth) {
int lastPositionPreviousMonth = firstWeekDay-1;
selectedDateBlock=lastPositionPreviousMonth-([selectedDate numDaysInMonth]-[selectedDate day]);
} else if (isSelectedDateNextMonth) {
selectedDateBlock = [currentMonth numDaysInMonth] + (firstWeekDay-1) + [selectedDate day];
}
NSDate *todayDate = [NSDate date];
int todayBlock = -1;
if ([todayDate month] == [currentMonth month] && [todayDate year] == [currentMonth year]) {
todayBlock = [todayDate day] + firstWeekDay - 1;
}
for (int i=0; i<numBlocks; i++) {
int targetDate;
int targetColumn = i%7;
int targetRow = i/7;
int targetX = targetColumn * (kVRGCalendarViewDayWidth)+2;
int targetY = kVRGCalendarViewTopBarHeight + targetRow * (kVRGCalendarViewDayHeight);
if (i<firstWeekDay) { //previous month
targetDate = (prevMonthNumDays-firstWeekDay)+(i+1);
NSString *hex = (isSelectedDatePreviousMonth) ? @"0x333333" : @"0x888888";
CGContextSetFillColorWithColor(context, [UIColor colorWithHexString:hex].CGColor);
} else if (i>=(firstWeekDay+currentMonthNumDays)) { //next month
targetDate = (i+1) - (firstWeekDay+currentMonthNumDays);
NSString *hex = (isSelectedDateNextMonth) ? @"0x333333" : @"0x888888";
CGContextSetFillColorWithColor(context, [UIColor colorWithHexString:hex].CGColor);
} else { //current month
targetDate = (i-firstWeekDay)+1;
NSString *hex = (isSelectedDatePreviousMonth || isSelectedDateNextMonth) ? @"0x888888" : @"0x333333";
CGContextSetFillColorWithColor(context, [UIColor colorWithHexString:hex].CGColor);
}
NSString *date = [NSString stringWithFormat:@"%i",targetDate];
//draw selected date
if (selectedDate && i==selectedDateBlock) {
CGContextAddArc(context, targetX+(kVRGCalendarViewDayWidth)/2, targetY+(kVRGCalendarViewDayHeight)/2, kVRGCalendarViewDayWidth/2-2, 0, 2*M_PI, 0);
CGContextSetFillColorWithColor(context, [UIColor colorWithHexString:@"0xf3ad39"].CGColor);
CGContextFillPath(context);
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
} else if (todayBlock == i) {
CGContextAddArc(context, targetX+(kVRGCalendarViewDayWidth)/2, targetY+(kVRGCalendarViewDayHeight)/2, kVRGCalendarViewDayWidth/2-2, 0, 2*M_PI, 0);
CGContextSetFillColorWithColor(context, [UIColor colorWithHex:0xf3ad39 alpha:0.5].CGColor);
CGContextFillPath(context);
CGContextSetFillColorWithColor(context, [UIColor colorWithHexString:@"0x333333"].CGColor);
}
[date drawInRect:CGRectMake(targetX, targetY+10, kVRGCalendarViewDayWidth, kVRGCalendarViewDayHeight) withFont:[UIFont fontWithName:@"HelveticaNeue" size:17] lineBreakMode:NSLineBreakByClipping alignment:NSTextAlignmentCenter];
}
// CGContextClosePath(context);
//Draw markings
if (!self.markedDates || isSelectedDatePreviousMonth || isSelectedDateNextMonth) return;
for (int i = 0; i<[self.markedDates count]; i++) {
id markedDateObj = [self.markedDates objectAtIndex:i];
int targetDate;
if ([markedDateObj isKindOfClass:[NSNumber class]]) {
targetDate = [(NSNumber *)markedDateObj intValue];
} else if ([markedDateObj isKindOfClass:[NSDate class]]) {
NSDate *date = (NSDate *)markedDateObj;
targetDate = [date day];
} else {
continue;
}
int targetBlock = firstWeekDay + (targetDate-1);
int targetColumn = targetBlock%7;
int targetRow = targetBlock/7;
int targetX = targetColumn * (kVRGCalendarViewDayWidth)+2;
int targetY = kVRGCalendarViewTopBarHeight + targetRow * (kVRGCalendarViewDayHeight) + 35;
//CGRect rectangle = CGRectMake(targetX+(kVRGCalendarViewDayWidth/2)-8,targetY,16,2);
//CGContextAddRect(context, rectangle);
CGContextAddArc(context, targetX+(kVRGCalendarViewDayWidth)/2+1, targetY, 2, 0, 2*M_PI, 0);
UIColor *color;
if (selectedDate && selectedDateBlock==targetBlock) {
color = [UIColor whiteColor];
} else if (todayBlock==targetBlock) {
color = [UIColor whiteColor];
} else {
color = (UIColor *)[markedColors objectAtIndex:i];
}
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillPath(context);
}
}
使用这个日历控件时需要注意,它是用在非arc环境中,但是代码里有些地方并没有对创建的对象做释放,可以通过静态代码分析可以找出并加上。另外它的delegate设置成retain,需要改成assign。