JTCalendar
JTCalendar 是一款适用于 iOS 的可自定义日历控件。
安装
使用 CocoaPods,将此行添加到您的 Podfile。
pod 'JTCalendar', '~> 2.0'
Carthage
要使用 Carthage 信任此项目,请将以下行添加到您的 Cartfile。
github "jonathantribouharet/JTCalendar" ~> 2.2
屏幕截图
警告
第 2 张截图中日历下方的部分没有提供。
特点
- 水平和垂直日历
- 可高度自定义,可以通过继承默认类或创建自己的类来实现协议
- 支持国际化
- 周视图模式
- 日期范围有限,您可以定义日历的开始日期和结束日期
用法
基本用法
您必须在您的 UIViewController
中创建两个视图
- 第一个视图是
JTCalendarMenuView
,它代表包含月份名称的部分。此视图是可选的。 - 第二个视图是
JTHorizontalCalendarView
或JTVerticalCalendarView
,它代表日历本身。
您的 UIViewController
必须实现 JTCalendarDelegate
,所有方法都是可选的。
#import <UIKit/UIKit.h>
#import <JTCalendar/JTCalendar.h>
@interface ViewController : UIViewController<JTCalendarDelegate>
@property (weak, nonatomic) IBOutlet JTCalendarMenuView *calendarMenuView;
@property (weak, nonatomic) IBOutlet JTHorizontalCalendarView *calendarContentView;
@property (strong, nonatomic) JTCalendarManager *calendarManager;
@end
JTCalendarManager
用于协调 calendarMenuView
和 calendarContentView
并提供默认行为。
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_calendarManager = [JTCalendarManager new];
_calendarManager.delegate = self;
[_calendarManager setMenuView:_calendarMenuView];
[_calendarManager setContentView:_calendarContentView];
[_calendarManager setDate:[NSDate date]];
}
@end
示例项目中包含了一些使用案例,您在提问前可以检查一下。
高级用法
即使 JTCalendarManager
的所有方法都是可选的,如果您不实现至少以下两个方法,您将无法取得很大进展:
calendar:prepareDayView:
此方法用于为特定日期自定义日视图的设计。每次在日视图中设置新的日期或每次当前页面更改时,都会调用此方法。您可以调用[_calendarManager reload];
来强制调用此方法。
- (void)calendar:(JTCalendarManager *)calendar prepareDayView:(JTCalendarDayView *)dayView
{
dayView.hidden = NO;
// Test if the dayView is from another month than the page
// Use only in month mode for indicate the day of the previous or next month
if([dayView isFromAnotherMonth]){
dayView.hidden = YES;
}
// Today
else if([_calendarManager.dateHelper date:[NSDate date] isTheSameDayThan:dayView.date]){
dayView.circleView.hidden = NO;
dayView.circleView.backgroundColor = [UIColor blueColor];
dayView.dotView.backgroundColor = [UIColor whiteColor];
dayView.textLabel.textColor = [UIColor whiteColor];
}
// Selected date
else if(_dateSelected && [_calendarManager.dateHelper date:_dateSelected isTheSameDayThan:dayView.date]){
dayView.circleView.hidden = NO;
dayView.circleView.backgroundColor = [UIColor redColor];
dayView.dotView.backgroundColor = [UIColor whiteColor];
dayView.textLabel.textColor = [UIColor whiteColor];
}
// Another day of the current month
else{
dayView.circleView.hidden = YES;
dayView.dotView.backgroundColor = [UIColor redColor];
dayView.textLabel.textColor = [UIColor blackColor];
}
// Your method to test if a date have an event for example
if([self haveEventForDay:dayView.date]){
dayView.dotView.hidden = NO;
}
else{
dayView.dotView.hidden = YES;
}
}
calendar:didTouchDayView:
此方法用于响应对日视图的触摸。例如,如果您想显示另一个月份,如果日视图来自另一个月份。
- (void)calendar:(JTCalendarManager *)calendar didTouchDayView:(JTCalendarDayView *)dayView
{
// Use to indicate the selected date
_dateSelected = dayView.date;
// Animation for the circleView
dayView.circleView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.1, 0.1);
[UIView transitionWithView:dayView
duration:.3
options:0
animations:^{
dayView.circleView.transform = CGAffineTransformIdentity;
[_calendarManager reload];
} completion:nil];
// Load the previous or next page if touch a day from another month
if(![_calendarManager.dateHelper date:_calendarContentView.date isTheSameMonthThan:dayView.date]){
if([_calendarContentView.date compare:dayView.date] == NSOrderedAscending){
[_calendarContentView loadNextPageWithAnimation];
}
else{
[_calendarContentView loadPreviousPageWithAnimation];
}
}
}
切换到周视图
如果您想要一次只查看一周,则需要将isWeekMode
设置为YES
并重新加载日历。
_calendarManager.settings.weekModeEnabled = YES;
[_calendarManager reload];
警告
当您更改模式时,它不会改变calendarContentView
的高度,您需要自己操作。更多细节请参阅示例项目。
自定义设计
为了自定义设计,您需要根据要自定义的部分实现一些方法。请检查JTCalendarDelegate文件和示例项目。
例如
// This method is independent from the date, it's call only at the creation of the dayView.
// For customize the dayView depending of the date use `prepareDayView` method
- (UIView<JTCalendarDay> *)calendarBuildDayView:(JTCalendarManager *)calendar
{
JTCalendarDayView *view = [JTCalendarDayView new];
view.textLabel.font = [UIFont fontWithName:@"Avenir-Light" size:13];
view.textLabel.textColor = [UIColor blackColor];
return view;
}
分页
内容视图(JTHorizontalCalendarView
和JTVerticalCalendarView
)仅仅是UIScrollView
的子类。每次当前页面更改时,将会调用calendarDidLoadNextPage
或calendarDidLoadPreviousPage
。内容视图提供了两个用于显示前一页或下一页的方法,带有动画loadNextPageWithAnimation
和loadPreviousPageWithAnimation
。您可以通过实现canDisplayPageWithDate
方法来限制日历的范围。
// Used to limit the date for the calendar
- (BOOL)calendar:(JTCalendarManager *)calendar canDisplayPageWithDate:(NSDate *)date
{
return [_calendarManager.dateHelper date:date isEqualOrAfter:_minDate andEqualOrBefore:_maxDate];
}
垂直日历
如果您使用JTVerticalCalendarView
创建垂直日历,您需要设置一些设置。
- (void)viewDidLoad
{
[super viewDidLoad];
_calendarManager = [JTCalendarManager new];
_calendarManager.delegate = self;
_calendarManager.settings.pageViewHaveWeekDaysView = NO; // You don't want WeekDaysView in the contentView
_calendarManager.settings.pageViewNumberOfWeeks = 0; // Automatic number of weeks
_weekDayView.manager = _calendarManager; // You set the manager for WeekDaysView
[_weekDayView reload]; // You load WeekDaysView manually
[_calendarManager setMenuView:_calendarMenuView];
[_calendarManager setContentView:_calendarContentView];
[_calendarManager setDate:[NSDate date]];
_calendarMenuView.scrollView.scrollEnabled = NO; // The scroll is not supported with JTVerticalCalendarView
}
国际化/本地化(更改第一周的第一天)
要更改区域设置和时间区域,只需这样做
_calendarManager.dateHelper.calendar.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"CDT"];
_calendarManager.dateHelper.calendar.locale = [NSLocale localeWithLocaleIdentifier:@"fr_FR"];
[_calendarManager reload];
在Swift中更改区域设置和时间区域请使用
let locale = Locale(identifier: "fr_FR")
let timeZone = TimeZone.init(abbreviation: "CDT")
calendarManager = JTCalendarManager(locale: locale, andTimeZone: timeZone)
日期比较
比较两个不同的日期时,要小心处理时区。提供了一些基本操作的辅助工具
[_calendarManager.dateHelper date:dateA isTheSameMonthThan:dateB];
[_calendarManager.dateHelper date:dateA isTheSameWeekThan:dateB];
[_calendarManager.dateHelper date:dateA isTheSameDayThan:dateB];
// Use to limit the calendar range
[_calendarManager.dateHelper date:date isEqualOrAfter:minDate andEqualOrBefore:maxDate];
优化
委托中的每个方法都是在主线程中调用的,您必须非常小心,特别是在调用非常频繁的 prepareDayView
方法时。
如果您需要从某个慢速设备获取数据,我建议您创建一个缓存,并在 prepareDayView
方法中查询此缓存。您必须从下一页缓存数据,并在加载新页面时(通过 calendarDidLoadNextPage
和 calendarDidLoadPreviousPage
方法)异步(在另一个线程中通过 dispatch_async
)更新此缓存。
问题
在提问之前,请确保探索示例项目。还要检查 JTCalendarDelegate 和 JTCalendarSettings 文件。
不要使用 NSLog
打印日期,请使用 NSDateFormatter
,因为 NSLog
并不处理时区。
NSDateFormatter *dateFormatter = [_calendarManager.dateHelper createDateFormatter];
dateFormatter.dateFormat = @"yyyy'-'MM'-'dd' 'HH':'mm':'ss";
NSLog(@"%@", [dateFormatter stringFromDate:yourDate]);
要求
- iOS 7 或更高版本
- 自动引用计数 (ARC)
作者
授权
JTCalendar遵循MIT许可协议发布。有关更多信息,请参阅LICENSE文件。